我有 2 个接口(interface)声明:
interface IStore { }
interface SomethingElse { a: number;}
还有 2 个实现每个类的类:
class AppStoreImplemetion implements IStore
{ }
class SomethingImplementation implements SomethingElse
{
a: 4;
}
我希望我的方法被赋予返回类型作为 "must be IStore
"的约束,所以我这样做了:
class Foo {
selectSync<T extends IStore>( ): T
{
return <T>{/* omitted*/ }; // I set the return type(`T`) when invoking
}
}
好的
测试:
这按预期工作:
new Foo().selectSync<AppStoreImplemetion>();
但这也有效 - 不如预期的那样:
new Foo().selectSync<SomethingImplementation>();
问题:
如何强制我的方法接受必须实现 IStore
的返回类型?
最佳答案
问题是 Typescript 使用结构类型来确定类型兼容性,因此接口(interface) IStore
是空的,与任何其他类型兼容,包括 SomethingElse
模拟标称类型(C#/Java 等中的类型)的唯一方法是添加一个字段,使接口(interface)与其他接口(interface)不兼容。您实际上不必使用该字段,您只需声明它以确保不兼容:
interface IStore {
__isStore: true // Field to ensure incompatibility
}
interface SomethingElse { a: number; }
class AppStoreImplemetion implements IStore {
__isStore!: true // not used, not assigned just there to implement IStore
}
class SomethingImplementation implements SomethingElse {
a = 4;
}
class Foo {
selectSync<T extends IStore>(): T {
return <T>{/* omitted*/ };
}
}
new Foo().selectSync<AppStoreImplemetion>();
new Foo().selectSync<SomethingImplementation>(); // This will be an error
请注意,任何具有 __isStore
的类都将是兼容的,无论它明确实现了 IStore
,同样是由于 Typescript 使用结构来确定兼容性,所以这有效:
class SomethingImplementation implements SomethingElse {
a = 4;
__isStore!: true
}
new Foo().selectSync<SomethingImplementation>(); // now ok
在实践中,IStore
可能会有更多的方法,所以这种偶然的兼容性应该很少见。
作为旁注,私有(private)字段确保不相关类的 100% 不兼容,因此如果有可能使 IStore
成为具有私有(private)字段的抽象类。这可以确保没有其他类意外兼容:
abstract class IStore {
private __isStore!: true // Field to ensure incompatibility
}
interface SomethingElse { a: number; }
class AppStoreImplemetion extends IStore {
}
class Foo {
selectSync<T extends IStore>(): T {
return <T>{/* omitted*/ };
}
}
new Foo().selectSync<AppStoreImplemetion>(); // ok
class SomethingImplementation implements SomethingElse {
private __isStore!: true;
a = 10;
}
new Foo().selectSync<SomethingImplementation>(); // an error even though we have the same private since it does not extend IStore
关于javascript - 使用 Typescript 强制接口(interface)的通用约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49549134/