是否可以在不在 Typescript 中调用的情况下设置函数的泛型类型?
Is it possible to set the generic type of a function without calling it in Typescript?
问题在标题里。下面是我正在努力实现的示例:
const apiResponse = Promise.resolve({data: 1} as {data: any}); // Assume I don't know the type of data
const mapData = <T>(res: {data: T}): T => res.data;
const x = apiResponse.then(mapData<number>); // This one fails to compile
const y = apiResponse.then(mapData); // Succeeded but y is of type any
const z = apiResponse.then(_ => mapData<number>(_)); // Succeeded but verbose !
const apiResponse = Promise.resolve( { data: 1, asType: ( data as any ).__proto__} as { data: any, asType: any } );
const mapData = <T>( res: { data: any, asType: { new( ...args ): T } } ): T => {
if ( res.data ) {
res.data.__proto__ = res.asType;
return res.data;
}
return undefined;
}
const y = apiResponse.then( mapData );
这就是你想要的吗?
就我个人而言,我认为您的 "verbose" 通话没有任何问题
const z = apiResponse.then(_ => mapData<number>(_));
但如果您想要其他内容,请继续阅读:
泛型函数类型,单个函数可以充当多种类型的函数,只允许您在调用时指定泛型类型参数。您的 mapData
函数具有以下类型:
type GenFunc = <T>(res: { data: T; }) => T
const verifyMapData: GenFunc = mapData; // okay
注意 GenFunc
不是泛型类型别名;它是一个特定的类型别名,指的是一个泛型函数类型。您可以将类型参数 T
视为 "belonging to" 调用签名,而不是函数名称或函数的任何类型别名的名称。由于它不属于函数名称,因此您不能单独编写 mapData<T>
并且由于它不属于 GenFunc
类型名称,因此您无法编写 GenFunc<T>
要么。
将此与不同但相关的 generic 类型别名进行比较,后者指的是 specific 函数类型家族:
type GenAlias<T> = (res: {data: T; }) => T
在这个类型中,泛型类型参数"belongs to"类型别名的名称,而不是它所代表的函数类型。
不幸的是,TypeScript 的类型系统目前确实缺乏采用 GenFunc
类型并自动生成 GenAlias<T>
类型所需的表现力。至少现在,你需要自己手写 GenAlias<T>
的类型定义,就像我刚才做的那样。
编译器可以做的是识别类型GenFunc
的值对于任何特定的[=18]都可以分配给类型GenAlias<T>
的变量=] 你想要的,所以下面的编译就好了:
const mapDataNumber: GenAlias<number> = mapData; // okay
因此,如果重要的话,您可以在不调用额外函数的情况下编译以下内容:
const w = apiResponse.then(mapDataNumber); // Promise<number>
此外,如果您不想在变量赋值上浪费一行,您可以使用 type assertion 来降低类型安全性但绝对没有运行时影响:
const v = apiResponse.then(mapData as GenAlias<number>); // Promise<number>
其中任何一个都适合您。
好的,希望对您有所帮助。祝你好运!
问题在标题里。下面是我正在努力实现的示例:
const apiResponse = Promise.resolve({data: 1} as {data: any}); // Assume I don't know the type of data
const mapData = <T>(res: {data: T}): T => res.data;
const x = apiResponse.then(mapData<number>); // This one fails to compile
const y = apiResponse.then(mapData); // Succeeded but y is of type any
const z = apiResponse.then(_ => mapData<number>(_)); // Succeeded but verbose !
const apiResponse = Promise.resolve( { data: 1, asType: ( data as any ).__proto__} as { data: any, asType: any } );
const mapData = <T>( res: { data: any, asType: { new( ...args ): T } } ): T => {
if ( res.data ) {
res.data.__proto__ = res.asType;
return res.data;
}
return undefined;
}
const y = apiResponse.then( mapData );
这就是你想要的吗?
就我个人而言,我认为您的 "verbose" 通话没有任何问题
const z = apiResponse.then(_ => mapData<number>(_));
但如果您想要其他内容,请继续阅读:
泛型函数类型,单个函数可以充当多种类型的函数,只允许您在调用时指定泛型类型参数。您的 mapData
函数具有以下类型:
type GenFunc = <T>(res: { data: T; }) => T
const verifyMapData: GenFunc = mapData; // okay
注意 GenFunc
不是泛型类型别名;它是一个特定的类型别名,指的是一个泛型函数类型。您可以将类型参数 T
视为 "belonging to" 调用签名,而不是函数名称或函数的任何类型别名的名称。由于它不属于函数名称,因此您不能单独编写 mapData<T>
并且由于它不属于 GenFunc
类型名称,因此您无法编写 GenFunc<T>
要么。
将此与不同但相关的 generic 类型别名进行比较,后者指的是 specific 函数类型家族:
type GenAlias<T> = (res: {data: T; }) => T
在这个类型中,泛型类型参数"belongs to"类型别名的名称,而不是它所代表的函数类型。
不幸的是,TypeScript 的类型系统目前确实缺乏采用 GenFunc
类型并自动生成 GenAlias<T>
类型所需的表现力。至少现在,你需要自己手写 GenAlias<T>
的类型定义,就像我刚才做的那样。
编译器可以做的是识别类型GenFunc
的值对于任何特定的[=18]都可以分配给类型GenAlias<T>
的变量=] 你想要的,所以下面的编译就好了:
const mapDataNumber: GenAlias<number> = mapData; // okay
因此,如果重要的话,您可以在不调用额外函数的情况下编译以下内容:
const w = apiResponse.then(mapDataNumber); // Promise<number>
此外,如果您不想在变量赋值上浪费一行,您可以使用 type assertion 来降低类型安全性但绝对没有运行时影响:
const v = apiResponse.then(mapData as GenAlias<number>); // Promise<number>
其中任何一个都适合您。
好的,希望对您有所帮助。祝你好运!