TypeScript:仅当 T 是某种类型时,使泛型接口 A 的某个方法可用
请看这段代码:
interface A<T> {
method1(): A<T>;
}
interface B<T extends Function> extends A<T> {
method2(): B<T>;
}
var foo: A<Function>;
foo.method1();
foo.method2();
我本以为 foo 可以与 B<Function> 类型兼容,但结果却得到 error TS2339: Property 'method2' does not exist on type 'A<Function>'。我能以某种方式重写接口 B 来让它工作吗?
实际上,我正在尝试修复 lodash 的 _.memoize 的类型定义:
// This should be OK. The type of result1 should be compatible with aFunction.
var result1 = _(aFunction).memoize().value();
// And this should be an error.
var result2 = _(aNonFunctionValue).memoize().value();
更新。 基本上,我的问题是:我能否为 A<T> 编写这样一个通用方法,使其仅在 T 是某个其他类型 U 的子类型时可用?
答案#1
我能以某种方式重写接口 B 以使它工作吗?
解决方案
这是代码:
interface A<T> {
method1(): A<T>;
}
interface B<T extends Function> extends A<T> {
method2(): B<T>;
}
interface A<T> {
method2<T extends Function>(): B<T>;
}
var foo: A<Function>;
foo.method1();
foo.method2(); // works!
达到解决方案
让我们退一步,思考一下我们想要工作的内容:
var foo: A<Function>;
foo.method2(); // Should work
这意味着 A<Function> 应该有 method2。所以:
interface A<T> {
method2<T extends Function>(): B<T>;
}
这个方法二对 T 增加了一个通用约束,并返回 B 类型的内容。
其余的在最终解决方案中很清楚 🌹
答案#2
结果 TypeScript 不支持这个。请参见 https://github.com/Microsoft/TypeScript/issues/1290
2019 更新:现在我们有了条件类型,这简直轻而易举:
interface A<T> {
method1(): A<T>;
method2: T extends Function ? () => A<T> : never;
}
declare var foo: A<Function>;
foo.method1();
foo.method2();
