Typescript 推导出泛型成员函数的返回类型

Posted

技术标签:

【中文标题】Typescript 推导出泛型成员函数的返回类型【英文标题】:Typescript deduce return type of member function of generic type 【发布时间】:2021-12-25 18:05:37 【问题描述】:

我有一些我正在尝试做的事情,但我不太确定如何在 typescript 中实现它。

我正在使用 discord.js,我正在尝试制作一个包装器来将 Discord.User | Discord.PartialUser(或类似的 T | PartialT 类型)转换为它们的非部分版本。

类似这样的:

interface Partial 
    partial: boolean;
    fetch(): Promise<any>;

async function departialize<T extends Partial>(thing: T) 
    if(thing.partial) 
        return await thing.fetch();
     else 
        return thing;
    

编译时,我想包含更多类型信息。 IE。在这个例子中,我希望它返回 Promise&lt;Discord.User&gt; 而不是 Promise&lt;Any&gt;

Discord.User.fetch()Discord.PartialUser.fetch()都返回Promise&lt;Discord.User&gt;,这可以在接口或返回类型中推导出来吗?在 C++ 中我们会写类似 decltype(std::declval&lt;T&gt;().fetch()) 的东西,但不确定在 TS 中该做什么。

【问题讨论】:

【参考方案1】:

想通了,这就是我要做的,以防它帮助其他人:

type PotentiallyPartial = Discord.AllowedPartial | Discord.Partialize<Discord.AllowedPartial>;

async function departialize<T extends PotentiallyPartial, R extends ReturnType<T["fetch"]>>(thing: T): Promise<R> 
    if(thing.partial) 
        return thing.fetch();
     else 
        return thing as R;
    
;

【讨论】:

【参考方案2】:

这是一个重载函数,它将为您的输入提供正确的返回类型,并根据partial 属性的推断值缩小范围。

注意事项:

因为 Partial utility 已经在 TypeScript 中声明,所以我使用类型名称 Incomplete 来避免编译器错误。

unknownany 更安全,但如果您确实需要 any,请随时更换。

TS Playground link

interface Incomplete<T = unknown> 
  partial: boolean;
  fetch (): Promise<T>;


function departialize <T extends Incomplete &  partial: true >(thing: T): ReturnType<T['fetch']>;
function departialize <T extends Incomplete &  partial: false >(thing: T): T;
function departialize <T extends Incomplete>(thing: T): T | ReturnType<T['fetch']>;
function departialize <T extends Incomplete>(thing: T): T | ReturnType<T['fetch']> 
  return thing.partial ? thing.fetch() as ReturnType<T['fetch']> : thing;


// Usage:

declare const input1: 
  partial: boolean;
  fetch (): Promise<string>;
  someOtherProp: number;
;

const output1 = departialize(input1); // typeof input1 | Promise<string>

declare const input2: 
  partial: true;
  fetch (): Promise<string>;
  someOtherProp: number;
;

const output2 = departialize(input2); // Promise<string>

declare const input3: 
  partial: false;
  fetch (): Promise<string>;
  someOtherProp: number;
;

const output3 = departialize(input3); // typeof input3

【讨论】:

以上是关于Typescript 推导出泛型成员函数的返回类型的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript--泛型

TypeScript--泛型

Typescript #6 泛型

TypeScript开发实战

前端进阶-TypeScript高级类型 | 泛型约束泛型接口泛型工具类型

在 TypeScript 中推断泛型函数类型