如何创建带强类型构造函数的TypeScript接口或类定义?
TypeScript 强类型构造函数的接口/类定义问题
我想创建带有强类型构造函数的TypeScript接口或类定义,查了相关问题还是没搞定。试了下面这些写法(可能在.d.ts文件里):
// 可能在.d.ts文件中 declare interface MyInterface{ // constructor(conArg: string) : ImplementInterface // 没用 - Type 'Function' is not assignable to type '(conArg: string) => ImplementInterface' // new(conArg : string) : ImplementInterface // 没用 - Type 'ImplementInterface' provides no match for the signature 'new (conArg: string): ImplementInterface' // new(conArg : string) : MyInterface // 没用 - Type 'ImplementInterface' provides no match for the signature 'new (conArg: string): MyInterface' myMethod(myArg : string) : string } declare class MyClass { constructor(conArg: string) myMethod(myArg : string) : string } // 实现代码 // 使用类 class ImplementClass implements MyClass{ // constructor(){} // 不管注释还是取消注释都不报错 :( // 预期应该报错:提示缺少构造函数或者参数不符合要求 myMethod(){ return '' } // 注释这行会报错,这才是预期的 :) } // 使用接口 class ImplementInterface implements MyInterface { // constructor(){} // 不管注释还是取消注释都不报错 :( // 预期应该报错:提示缺少构造函数或者参数不符合要求 myMethod(){ return '' } // 注释这行会报错,这才是预期的 :) }
问题就在于:实现类的时候,不管有没有写符合要求的构造函数,都不会触发错误,但我觉得这时候应该报错才对。
为啥会这样?
TypeScript的规则里,接口只会检查类的实例成员,构造函数属于类的静态成员,不在接口的校验范围内。就算用implements去实现一个已声明的类,也只会匹配实例方法/属性,不会管构造函数的签名。
解决办法
1. 用抽象类(最直接)
如果要强制子类必须实现特定构造函数,别用接口,改用抽象类:
abstract class MyAbstractClass { constructor(public conArg: string) {} abstract myMethod(myArg: string): string; } // 这里必须写符合签名的构造函数,不然直接报错 class ImplementClass extends MyAbstractClass { // 取消注释下面这行就会报错:派生类的构造函数必须包含 'super' 调用 // constructor() {} // 正确写法 constructor(conArg: string) { super(conArg); } myMethod(myArg: string): string { return ''; } }
抽象类的构造函数会被子类继承,子类必须调用super,这就强制了子类要么定义匹配的构造函数,要么显式调用父类的构造函数,完美解决构造函数校验的问题。
2. 单独定义构造函数类型+泛型约束(适合必须用接口的场景)
如果一定要用接口,可以单独定义构造函数的类型,然后通过函数的泛型约束来检查类的构造函数:
interface MyInterface { myMethod(myArg: string): string; } // 定义构造函数的类型 type MyConstructor = new (conArg: string) => MyInterface; // 用这个函数来创建实例,同时校验类的构造函数 function createInstance<T extends MyConstructor>(ctor: T, conArg: string): InstanceType<T> { return new ctor(conArg); } // 反例:构造函数不符合要求,createInstance会报错 class BadImplement implements MyInterface { constructor() {} myMethod(myArg: string): string { return ''; } } // 取消注释下面这行会报错:类型 'typeof BadImplement' 的参数不能赋给类型 'MyConstructor' 的参数 // createInstance(BadImplement, "test"); // 正确实现 class GoodImplement implements MyInterface { constructor(conArg: string) {} myMethod(myArg: string): string { return ''; } } createInstance(GoodImplement, "test"); // 正常运行
这种方式是通过函数的泛型约束间接检查类的构造函数是否符合要求,虽然不如抽象类直接,但能满足必须用接口的场景。
内容的提问来源于stack exchange,提问作者user70587
相关产品推荐
相关产品推荐

