Typescript:如何在使用.map时保留长度信息



我的当前"工作";方法是:

const generateMainOrientations = <T extends readonly string[]>(
mainOrientationsNames: T
): { [Index in keyof T]: Orientation } => {
const temp: Orientation[] = mainOrientationsNames.map(
mainOrientationName => ({
name: mainOrientationName,
getYear(date) {
return date.getFullYear()
},
getRecordContent: getMainOrientationRecordContent
})
)
return temp as unknown as { [Index in keyof T]: Orientation }
}
const mainOrientations = generateMainOrientations([
"One",
"Two",
"Three"
] as const)

然而,我必须使用as unknown as { [Index in keyof T]: Orientation },这并不理想,否则(即使从temp变量中删除类型断言(,它也会抛出

Type '{ name: string; getYear(date: any): any; getRecordContent: (values: number[]) => string[]; }[]' is not assignable to type '{ [Index in keyof T]: Orientation; }'.ts(2322)

然而,{ name: string; getYear(date: any): any; getRecordContent: (values: number[]) => string[]; }Orientation的定义

这表明在使用地图后,任何长度信息都会丢失。

有没有一种更有机的方法来实现这一点,最好根本不必使用类型断言,或者至少不必使用as unknown。目标是使mainOrientations成为Orientation的元组,其长度与传递给generateMainOrientations的参数相同,因此在本例中为[Orientation, Orientation, Orientation](而不是Orientation[](。

游乐场

您需要重载您的函数:

interface Orientation {
name: string,
getYear(date: Date): number,
getRecordContent(values: number[]): string[]
}
declare function getMainOrientationRecordContent(values: number[]): string[]
function generateMainOrientations<T extends string, Tuple extends T[]>(
mainOrientationsNames: [...Tuple]
): { [Index in keyof Tuple]: Orientation }
function generateMainOrientations(
mainOrientationsNames: string[]
) {
return mainOrientationsNames.map(
mainOrientationName => ({
name: mainOrientationName,
getYear: (date: Date) => date.getFullYear(),
getRecordContent: getMainOrientationRecordContent
})
)
}
// [Orientation, Orientation, Orientation]
const mainOrientations = generateMainOrientations([
"One",
"Two",
"Three"
])

游乐场

请记住,一旦使用Array.prototype.map,typescript就不会保留结果的长度。在这里你可以找到原因。

因此,只有两个选项:重载和类型断言。

如果将name属性参数化,则可以做得更好:

interface Orientation<Name extends string> {
name: Name,
getYear(date: Date): number,
getRecordContent(values: number[]): string[]
}
declare function getMainOrientationRecordContent(values: number[]): string[]
function generateMainOrientations<T extends string, Tuple extends T[]>(
mainOrientationsNames: [...Tuple]
): { [Index in keyof Tuple]: Orientation<Tuple[Index] & string> }
function generateMainOrientations(
mainOrientationsNames: string[]
) {
return mainOrientationsNames.map<Orientation<string>>(
name => ({
name,
getYear: (date) => date.getFullYear(),
getRecordContent: getMainOrientationRecordContent
})
)
}
// [Orientation<"One">, Orientation<"Two">, Orientation<"Three">]
const mainOrientations = generateMainOrientations([
"One",
"Two",
"Three"
])

您可以使用temp as any

const generateMainOrientations = <T extends readonly string[]>(
mainOrientationsNames: T
): { [Index in keyof T]: Orientation } => {
const temp = mainOrientationsNames.map((mainOrientationName) => ({
name: mainOrientationName,
getYear(date: Date) {
return date.getFullYear();
},
getRecordContent: getMainOrientationRecordContent
}));
return temp as any;
};

最新更新