簡體   English   中英

通用函數的 Typescript ReturnType

[英]Typescript ReturnType of generic function

TypeScript 2.8 中的新ReturnType是一個非常有用的功能,可讓您提取特定函數的返回類型。

function foo(e: number): number {
    return e;
}

type fooReturn = ReturnType<typeof foo>; // number

但是,我在通用函數的上下文中使用它時遇到了麻煩。

function foo<T>(e: T): T {
    return e;
}

type fooReturn = ReturnType<typeof foo>; // type fooReturn = {}

type fooReturn = ReturnType<typeof foo<number>>; // syntax error

type fooReturn = ReturnType<(typeof foo)<number>>; // syntax error

有沒有辦法提取泛型函數給定特定類型參數的返回類型?

如果你想得到一些特殊的泛型類型,你可以使用一個假函數來包裝它。

const wrapperFoo = () => foo<number>()
type Return = ReturnType<typeof wrapperFoo>

更復雜的演示

function getList<T>(): {
  list: T[],
  add: (v: T) => void,
  remove: (v: T) => void,
  // ...blahblah
}
const wrapperGetList = () => getList<number>()
type List = ReturnType<typeof wrapperGetList>
// List = {list: number[], add: (v: number) => void, remove: (v: number) => void, ...blahblah}

這是我目前用於提取未導出的內部類型的導入庫(如 knex)的工作解決方案:

// foo is an imported function that I have no control over
function foo<T>(e: T): InternalType<T> {
    return e;
}

class Wrapper<T> {
  // wrapped has no explicit return type so we can infer it
  wrapped(e: T) {
    return foo<T>(e)
  }
}

type FooInternalType<T> = ReturnType<Wrapper<T>['wrapped']>
type Y = FooInternalType<number>
// Y === InternalType<number>

如果您可以更改函數定義,我找到了一種很好且簡單的方法來實現這一點。 就我而言,我需要將 typescript 類型Parameters與泛型函數一起使用,正是我在嘗試Parameters<typeof foo<T>>並且實際上它不起作用。 所以最好的方式實現這一目標是通過一個接口函數定義改變功能的定義,這也將與打字稿類型工作ReturnType

以下是 OP 描述的案例的示例:

function foo<T>(e: T): T {
   return e;
}

type fooReturn = ReturnType<typeof foo<number>>; // Damn! it throws error

// BUT if you try defining your function as an interface like this:

interface foo<T>{
   (e: T): T
}

type fooReturn = ReturnType<foo<number>> //it's number, It works!!!
type fooParams = Parameters<foo<string>> //it also works!! it is [string]

//and you can use the interface in this way
const myfoo: foo<number> = (asd: number) => {
    return asd;
};

myfoo(7);
const wrapperFoo = (process.env.NODE_ENV === 'development' ? foo<number>() : undefined)!
type Return = typeof wrapperFoo

代替NODE_ENVdevelopment ,我什NODE_ENV會使用test或一些隨機字符串,比如typescript_helper (只要 TypeScript 不拋出錯誤),這樣它就永遠不會執行,因為它不會在運行時使用。

我找到了解決方案。 您決定它是否適合您的需求:)

使用接口聲明函數參數和返回類型

interface Foo<T, V> {
  (t: T, v: V): [T, V]
}

使用ParametersReturnType這種方式實現您的函數

function foo<T, V>(...[t, v]: Parameters<Foo<T, V>>): ReturnType<Foo<T, V>> {
  return [t, v]; // [T, V]
}

正常調用您的函數,或使用ReturnType獲取返回類型

foo(1, 'a') // [number, string]
type Test = ReturnType<Foo<number, number>> // [number, number]

TypeScript 編譯器不會將typeof foo視為泛型類型。 我會說這是編譯器中的一個錯誤。

但是,TypeScript 具有可調用接口,這些接口可以是通用的,沒有任何問題,因此如果您引入與函數簽名兼容的可調用接口,則可以像這樣實現自己的ReturnType等價物:

function foo<T>(x: T): T {
  return x;
}


interface Callable<R> {
  (...args: any[]): R;
}

type GenericReturnType<R, X> = X extends Callable<R> ? R : never;

type N = GenericReturnType<number, typeof foo>; // number

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM