#typescript
#машинописный текст #typescript
Вопрос:
Я хочу преобразовать тип кортежа [T1, T1]
в какой-то другой [T2, T2]
, где T2
это подтип T1
. Пока это моя лучшая попытка, но я не смог определить возвращаемый тип на variadicMapping
. Я предполагаю, что решение включает в себя недавно введенные вариационные типы кортежей.
type T1 = { property: string };
type T2 = T1 amp; { otherProperty: number };
const transformType = <T extends T1>(obj: T): T2 => ({
...obj,
otherProperty: 0,
});
const variadicMapping = <T extends T1[]>(objects: T) => {
return objects.map((e) => transformType(e));
};
const foo = [{property: 'propertyA' }, { property: 'propertyB' }] as [T1, T1];
const bar = variadicMapping(foo); // T2[] instead of [T2, T2]
Ответ №1:
Для этого вам не нужны переменные типы кортежей. Проблема в том, что определение стандартной библиотеки TypeScript для Array.prototype.map()
не пытается представить тот факт, что длина массива сохраняется. Существует открытая проблема, Microsoft / TypeScript # 29841, с просьбой решить эту проблему.
Если вам нужно, чтобы компилятор обращал внимание на длину, вам нужно будет использовать свой собственный набор текста для map()
, скажем, слияния объявлений. Возможно, что-то вроде этого:
interface Array<T> {
map<U>(
callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any
): { [K in keyof this]: U };
}
Я использую отображенные типы кортежей для представления сохранения длины, и, в частности, полиморфный this
, чтобы отразить тот факт, что мы хотим перебирать ключи любого подтипа Array<T>
, который мы, оказывается, используем, например, кортеж.
Но вмешательство в определения таких часто используемых методов может привести к неожиданным результатам в других частях вашей базы кода, поэтому, если вы не хотите беспокоиться о том, должно ли каждое использование map()
вести себя таким образом, вы можете использовать утверждение типа, чтобы сообщить компилятору, что результат этого конкретного вызова map()
имеет определенную длину и тип:
const variadicMapping = <T extends T1[]>(objects: T) => {
return objects.map((e) => transformType(e)) as { [K in keyof T]: T2 };
};
В любом случае вы должны получить желаемое поведение:
const bar = variadicMapping(foo); // [T2, T2]