我试图弄清楚如何在类中获取泛型函数的返回类型。
例如,
declare class Test {
open<T, R>(t1: T, t2: R): T | R;
}
type TestType<T, R> = (Test['open'])<T, R>;
type TestTypeReturn = ReturnType<TestType<number, number>>;
但是,我在...])<T, R>
的第4条非空白行出现错误,说应该使用分号。我不确定我想做什么。有人知道吗?
答案 0 :(得分:1)
大概对于显示的特定示例,您可以手动写出所需的类型,例如:
type TestTypeManual<T, R> = (t1: T, t2: R) => T | R;
type TestTypeReturnManual = ReturnType<TestTypeManual<number, number>>; // number
但是您想让编译器为您完成这项工作。
TypeScript的类型系统缺乏表达表示通用函数类型(如{{1})的具体类型别名和引用type GenFunc = <T>(x: T)=>T
的具体类型别名之间的关系所需的表达能力。您必须先调用通用函数,才能指定通用函数的类型参数。因此,即使有了上述内容,即使您可以调用类型为type GenAlias<T> = (x:T)=>T
的函数,例如GenFunc
,也没有像genFunc<string>("hello")
这样的 type 。有一个开放的suggestion (microsoft/TypeScript#17574),它可能允许进行这种更高级别的操作,但我不知道我们是否可以期望在那里进行任何移动。
目前,似乎还没有办法完全在类型级别上做到这一点。
如果您不介意某些可能对所发出的JavaScript产生影响的hack,则可以利用对TypeScript 3.4中添加的inferring generic functions的某些支持。这就是我可能会做的。首先,在这样的地方引入函数声明:
GenFunc<string>
// you could just declare this instead of implementing it, but whatever:
function magicThunk<A extends any[], R>(f: (...args: A) => R): () => (...args: A) => R {
return () => f;
}
函数可能只是采用了一个回调函数magicThunk()
并返回了一个新的no-arg函数,该函数返回了f
,这看起来并不神奇(但它是{{ 3}},至少)。但是,如果您使用通用函数调用f
,那么从TS3.4开始会发生一件有趣的事情:
magicThunk()
返回的函数也是 泛型的,但是泛型类型参数已向外移动了一层。现在,您可以调用thunk的泛型函数并指定其类型参数,从而获得非泛型函数:
const genericIdentity = <T>(x: T) => x; // <T>(x: T) => T
const thunkIdentity = magicThunk(genericIdentity); // <T>() => (x: T) => T
这正是我们想要的“指定通用函数的类型参数而不调用它”的操作。
无论如何,我们几乎都在那儿...最后一步是创建一个新的 generic const stringIdentity = thunkIdentity<string>(); // (x: string) => string;
,使我们能够将一些类型参数带入范围,而无需将它们直接放在另一个函数中。这是我为您的class
类型执行的操作:
Test["open"]
现在class TransformTest<T, R> {
open = magicThunk(new Test().open)<T, R>()
}
的类型应该是您要寻找的类型:
TransformTest<T, R>.open
一切正常。请注意,您无需在代码中实际调用type TestType<T, R> = TransformTest<T, R>["open"]; // (t1: T, t2: R) => T | R
type TestTypeReturn = ReturnType<TestType<number, number>>; // number
或构造magicThunk()
的实例(这很好,因为我认为TransformTest
不会被正确绑定);编译器在设计时就完成了您需要的所有工作;它只是必须经过评估将要发出的代码类型的动作。
好的,希望能有所帮助;祝你好运!