TypeScript编译器未检测到混入抽象类未实现的getter问题
问题:TypeScript未检测到未实现的抽象属性
interface 根据@artur-grzesiak的评论,我们修改了示例,简化版本移除了命名不当的interface方法,但仍预期编译器会对未实现的interface属性抛出错误,然而并未出现。
type GConstructor<T = {}> = abstract new (...args: any[]) => T; // 原始对象接口 interface IBaseDataObject { readonly id: string; } // 名称模式接口 interface Name { name: string; } // 类必须实现的接口 interface BaseDataObjectInterface<T extends IBaseDataObject> { readonly id: string; readonly interface: T; } abstract class AbstractBaseObject<T extends IBaseDataObject> { readonly id: string; abstract readonly interface: T constructor( iBaseDataObject: T ) { this.id = iBaseDataObject.id; } } type AbstractBaseObjectCtor<T extends IBaseDataObject> = GConstructor<AbstractBaseObject<T>>; // 国家相关的接口、类定义 interface ICountry extends IBaseDataObject, Name {} function NameAbstractMixin<TBase extends AbstractBaseObjectCtor<T>, T extends IBaseDataObject & Name>(Base: TBase) { abstract class NamedBase extends Base implements Name { readonly name: string; constructor(...args: any[]) { super(...args) this.name = args[0].name; } } return NamedBase; } class Country extends NameAbstractMixin(AbstractBaseObject<ICountry>) implements BaseDataObjectInterface<ICountry> { // get interface(): ICountry { // return { // id : "hello", // name: "France", // } // } }
问题详情
Country类继承了通过混入创建的抽象类(基类为AbstractBaseObject<ICountry>),AbstractBaseObject声明了抽象属性interface,同时Country类还实现了要求该属性的BaseDataObjectInterface<ICountry>,但TypeScript编译器并未检测到该属性未实现的错误,请问是否遗漏了什么?
原因与解决方案
这是TypeScript对JavaScript保留字的特殊处理导致的问题:
interface是JavaScript的保留字,虽然TypeScript允许在特定场景下使用保留字作为成员名称,但编译器对这类名称的抽象属性检查存在漏洞,无法正常触发未实现的错误提示。- 另外,当类继承抽象类时,编译器会默认认为抽象类的抽象成员已经满足了接口的要求,不会再强制子类去实现——但如果成员名称是保留字,这个检查逻辑会失效得更明显。
解决办法:
- 直接修改属性名称,避免使用保留字,比如改成
dataInterface:// 修改接口 interface BaseDataObjectInterface<T extends IBaseDataObject> { readonly id: string; readonly dataInterface: T; } // 修改抽象类 abstract class AbstractBaseObject<T extends IBaseDataObject> { readonly id: string; abstract readonly dataInterface: T; constructor(iBaseDataObject: T) { this.id = iBaseDataObject.id; } } // 此时Country类如果不实现dataInterface,编译器会正常报错 - 如果一定要使用
interface作为名称,可以用引号包裹("interface"),但这种写法会降低代码可读性,不推荐:abstract class AbstractBaseObject<T extends IBaseDataObject> { readonly id: string; abstract readonly "interface": T; }
内容的提问来源于stack exchange,提问作者viduvern
相关产品推荐
相关产品推荐

