TypeScript:是否可以强制接口签名中的泛型类型与实现该接口的类的类型相同



我想强制接口签名中声明的泛型与实现该接口的类的类型相同。类似以下代码:

interface I1<T = typeof this> {
aAnyMethod(): I1<T>;
}
class C1 { }
class C2 implements I1<C1> /* accepts C1 but shouldn't, it should only accept C2 */ {
// ok. It works as it should
aAnyMethod(): C2 {
return new C2;
}
}
class C3 implements I1{
// not accepted. It works as it should
aAnyMethod(): C1 {
return new C1;
}
}

您可以给类型参数一个自引用的上界。这是这个问题的标准解决方案,例如在Java的接口Comparable<T extends Comparable<T>>中使用。

interface MyInterface<T extends MyInterface<T>> {
someMethod(): T;
}
class Works implements MyInterface<Works> {
someMethod() { return new Works(); }
foo() { return 'foo'; }
}
// error: Type 'SomethingElse' does not satisfy the constraint 'MyInterface<SomethingElse>'.
class DoesntWork implements MyInterface<SomethingElse> {
someMethod() { return new SomethingElse(); }
}

不幸的是,这样的东西仍然有效:

// No error, because Works extends MyInterface<Works>
class ShouldntWorkButDoes implements MyInterface<Works> {
someMethod() { return new Works(); }
baz() { return 'baz'; }
}

然而,这不会造成问题,因为在任何地方,如果你想接受实现MyInterface的东西,你都可以要求它实现自己的MyInterface<...>

function acceptsMyInterface<T extends MyInterface<T>>(arg: T) {}
// OK
acceptsMyInterface(new Works());
// error: Argument of type 'ShouldntWorkButDoes' is not assignable to parameter of type 'MyInterface<ShouldntWorkButDoes>'.
acceptsMyInterface(new ShouldntWorkButDoes());

所以ShouldntWorkButDoes只在声明它的地方工作,而不是在使用它的地方。(请注意,为了进行此演示,我必须添加一些成员foobaz,这样Typescript就不会将这些类型视为结构等效。(

游乐场链接

最新更新