Общее ограничение для переменных нескольких типов

Пишу типы для существующей библиотеки. Я столкнулся с проблемой определения ограничения для типа, когда два типа переменных должны удовлетворять некоторому ограничению (T1 [T2] должен быть массивом определенного типа).

У меня 1-й интерфейс

interface GenericInterfaceWithArray<ElementType> {
  arrayOfElements: ElementType[];
  push: (value: ElementType) => void;
}

и второй, который использует предыдущий, а также имеет 2 переменных типа:

interface OuterInterface<
  ObjectContainingArray,
  KeyOfPropertyWithArray extends keyof ObjectContainingArray
> {
  nestedProperty: GenericInterfaceWithArray<ObjectContainingArray[KeyOfPropertyWithArray]>;
  // line above has incorrect definition because
  // ObjectContainingArray[KeyOfPropertyWithArray] is an array
  // - can I take type from 'first array element' here?
  // smth like this line below

  // GenericInterfaceWithArray<ObjectContainingArray[KeyOfPropertyWithArray][0]>;
  // this does not work:
  // `Type '0' cannot be used to index type 'ObjectContainingArray[KeyOfPropertyWithArray]'.`
}

Использование:

interface InterfaceWithArrayProp {
  arrayProp: number[];
}

const myType: OuterInterface<InterfaceWithArrayProp, 'arrayProp'>;
myType.nestedProperty.push(25); // here should be validation for `number`.
// Currently I have type: `number[]`

Я пробовал определить внутренний интерфейс альтернативным способом: как общий для массива (менее удовлетворительный, но приемлемый, если нет возможности для первой версии):

interface GenericInterfaceWithArray<ArrayOfElements extends Array<any>> {
  arrayOfElements: ArrayOfElements;
  push: (value: ArrayOfElements[0]) => void;
}

Но теперь у меня ошибка от OuterInterface: Type 'ObjectContainingArray[KeyOfPropertyWithArray]' does not satisfy the constraint 'any[]'.

Можно ли определить, что T1[T2] является массивом, и передать тип этого первого элемента в качестве параметра для другого универсального интерфейса?


person Krzyrok    schedule 14.05.2019    source источник


Ответы (1)


Хорошо, я понял, что могу использовать условные типы.

type FirstArrayElement<ElementsArrayType> = ElementsArrayType extends any[] ? ElementsArrayType[0] : never;

interface OuterInterface<
  ObjectContainingArray,
  KeyOfPropertyWithArray extends keyof ObjectContainingArray
> {
  nestedProperty: GenericInterfaceWithArray<FirstArrayElement<ObjectContainingArray[KeyOfPropertyWithArray]>>;
}
person Krzyrok    schedule 14.05.2019