TypeScript 中有两种不同风格的泛型:泛型 functions 和泛型 types...看起来您希望编译器将一种转换为另一种给你,不直接支持。
要明确:
Generic types 具有需要指定的类型参数,然后才能将它们用作特定类型。例如:
type GenType<T> = (x: T) => T[];
declare const oops: GenType; // error
declare const genT: GenType<string>; // okay
const strArr = genT("hello"); // string[];
const numArr = genT(123); // error!
这里,GenType 是一个泛型类型。需要指定类型参数才能将其用作值的类型,然后生成的类型就不再是泛型了。 genT 函数接受 string 并返回 string[]。它不能用作接受number 并返回number[] 的函数。
另一方面,
通用函数有一个特定的类型,可以像任何可能的类型参数替换一样。泛型函数类型的值在使用时仍然是泛型的。类型参数附在调用签名中:
type GenFunc = <T>(x: T) => T[];
declare const genF: GenFunc;
const strArr = genF("hello"); // strArr: string[];
const numArr = genF(123); // numArr: number[];
这里,GenFunc 是指泛型函数的特定类型。 genF 函数在被调用时仍然是泛型的。
泛型函数(包括泛型构造函数)可以被认为是generic values,而不是泛型类型。
这两种泛型是相互关联的,但 TypeScript 类型系统的表达力不足以讨论它们之间的关系。在其他一些语言中,您也许可以根据其他语言来定义一个类似
type GenFunc = forall T, GenType<T>; // not TS, error
或
type GenType<T> = instantiate GenFunc with T; // not TS, error
但在 TypeScript 中你不能。也许如果我们得到microsoft/TypeScript#1213 中要求的更高种类的类型...但不是现在。所以不能直接在类型系统中以编程方式将GenFunc变成GenType。
有一些邪恶的可怕方法可以强制编译器根据GenFunc 计算GenType。我知道的方式利用了泛型类属性初始化和 TypeScript 3.4 中引入的一些 higher order type inference for generic functions。当我实际上没有任何值时,我让编译器认为它正在计算值,然后获取这些假装值之一的类型:
class GenTypeMaker<T> {
getGenType!: <A extends any[], R>(cb: (...a: A) => R) => () => (...a: A) => R;
genType = this.getGenType(null! as GenFunc)<T>()
}
type GenType2<T> = GenTypeMaker<T>['genType']
// type GenType2<T> = (x: T) => T[]
您可以验证GenType2<T> 与GenType<T> 的类型相同,如果您将GenFunc 更改为具有一个类型参数的任何泛型函数,GenType2<T> 将相应更改。
但我不知道我想推荐任何人实际使用这种方法。而且它并没有真正缩放或组合;如果您在一个类型参数中有一个充满泛型函数的对象,并且您想将其转换为一个充满具有指定类型参数的特定函数的对象,则无法使用此方法从类型系统中获取它而无需执行一次对于每个对象属性。
无论如何,希望对您有所帮助;祝你好运!
Playground link to code