【问题标题】:Is it possible to set the generic type of a function without calling it in Typescript?是否可以设置函数的泛型类型而不在 Typescript 中调用它?
【发布时间】:2020-04-05 01:01:27
【问题描述】:

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

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 !

【问题讨论】:

标签: typescript typescript-generics


【解决方案1】:

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

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

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


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

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

注意GenFunc 不是泛型类型别名;它是一个特定的类型别名,指的是泛型函数类型。您可以将类型参数T 视为“属于”调用签名,而不是函数的名称或函数的任何类型别名的名称。因为它不属于函数的名字你不能单独写mapData&lt;T&gt;,因为它不属于GenFunc类型名你也不能写GenFunc&lt;T&gt;


将此与不同但相关的 generic 类型别名进行比较,后者指的是一系列特定函数类型:

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

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

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


编译器可以做的是识别GenFunc类型的值可以分配给你想要的任何特定T类型的变量GenAlias&lt;T&gt;,所以下面的编译就好了:

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

【讨论】:

  • 感谢您的高质量回复。这是你最后几天第二次给我保存论文 2 ;-)。
【解决方案2】:
        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 );

这就是你所追求的吗?

【讨论】:

  • 我不认为。我绝对不明白您要做什么:D。
  • 如果在响应中传递了值和实际类型,那么您可以通过将类型原型对象分配给值对象来推断响应中的类型
猜你喜欢
  • 1970-01-01
  • 2019-11-04
  • 2019-09-19
  • 1970-01-01
  • 2023-01-03
  • 2020-07-10
  • 2023-03-29
  • 2018-07-03
  • 1970-01-01
相关资源
最近更新 更多