是否可以设置函数的通用类型而无需在Typescript中调用它?

时间:2019-12-11 17:21:01

标签: typescript typescript-generics

问题在标题中。下面是我要实现的示例:

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 !

2 个答案:

答案 0 :(得分:1)

我个人认为您的“冗长”通话没有任何问题

const z = apiResponse.then(_ => mapData<number>(_)); 

但是,如果您还需要其他内容,请继续阅读:


泛型函数类型,其中一个函数可以充当多种类型的函数,只能让您在调用泛型类型参数时指定它。您的mapData函数具有以下类型:

type GenFunc = <T>(res: { data: T; }) => T
const verifyMapData: GenFunc = mapData; // okay

请注意,GenFunc不是通用类型别名。它是一个特定的类型别名,它引用泛型函数类型。您可以将类型参数T视为“属于”调用签名,而不是函数的名称或函数的任何类型别名的名称。由于它不属于函数名称,因此您不能自己编写mapData<T>,并且由于它不属于GenFunc类型名称,因此您不能编写GenFunc<T>要么。


将此与独特但相关的泛型类型别名进行比较,该别名指的是 specific 函数类型的族:

type GenAlias<T> = (res: {data: T; }) => T

在这种类型中,泛型类型参数“属于”类型别名的名称,而不是其表示的函数类型。

不幸的是,现在TypeScript的类型系统缺乏采用GenFunc类型并自动生成GenAlias<T>类型所必需的表达能力。至少目前,您需要像我刚才那样手动写出GenAlias<T>的类型定义。


编译器 所做的工作是,对于您想要的任何特定GenFunc,类型GenAlias<T>的值都可以分配给类型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>

其中任何一种都可以为您工作。


好的,希望能有所帮助。祝你好运!

Link to code

答案 1 :(得分:0)

        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 );

这是你的追求吗?