如何在TypeScript接口中引用动态自身类型关联构造函数与实例键?
解决方案:用泛型关联构造函数与实例键
你遇到的问题根源在于,接口中的this['cstr']无法在类型检查阶段被解析为具体的构造函数类型——接口本身没有实例上下文,TypeScript会将其视为unknown,自然无法关联到实例的键。
解决这个问题的核心是用泛型将构造函数类型与实例键的类型绑定,具体实现如下:
泛型接口方案
定义一个带泛型参数的接口,泛型参数代表构造函数的类型,以此约束key必须是该构造函数实例的有效键:
class Foo { bar?: string; } // 泛型接口,T约束为无参构造函数类型 interface IClassDescriptor<T extends new () => unknown> { cstr: T; // key必须是T对应实例的键 key: keyof InstanceType<T>; } // 显式指定泛型参数,此时key只能是Foo实例的键 const a: IClassDescriptor<typeof Foo> = { cstr: Foo, key: 'bar' // 合法,无报错 }; // 错误示例,符合预期报错:"baz"不是Foo实例的键 const b: IClassDescriptor<typeof Foo> = { cstr: Foo, key: 'baz' };
简化写法:自动推断泛型
如果不想手动指定泛型参数,可以用satisfies关键字或者工厂函数让TypeScript自动推断类型:
方式1:使用satisfies
// 无需手动指定泛型,TS自动推断T为typeof Foo const c = { cstr: Foo, key: 'bar' } satisfies IClassDescriptor<typeof Foo>;
方式2:工厂函数
function createDescriptor<T extends new () => unknown>(desc: IClassDescriptor<T>) { return desc; } // TS自动推断泛型参数,代码更简洁 const d = createDescriptor({ cstr: Foo, key: 'bar' // 合法 }); const e = createDescriptor({ cstr: Foo, key: 'baz' // 报错,符合预期 });
这种方案能完美实现你想要的约束:cstr和key始终保持关联,有效键通过类型检查,无效键则触发报错。
内容的提问来源于stack exchange,提问作者Mihi
相关产品推荐
相关产品推荐

