TypeScript泛型报错:MyDto不满足Record<string, unknown>约束
TypeScript泛型约束与类型兼容问题解答
问题1:MyDto不满足Record<string, unknown>约束
原因
Record<string, unknown>要求类型必须具备字符串索引签名,意味着可以用任意字符串作为键访问该类型的属性。但MyDto仅定义了name和age两个明确属性,未声明索引签名,TypeScript会判定它不满足Record<string, unknown>的约束——因为Record允许任意字符串键,而MyDto只支持特定键。
解决方案
修改抽象类的泛型约束,将Record<string, unknown>替换为更宽松的object(代表所有非原始类型,包含类实例),既保留MyDto的类型安全性,又放宽抽象类的约束:
abstract class MyAbstractClass<T extends object = object> { constructor(public readonly title: string, public readonly data: T) {} }
如果确实需要确保T的属性均为字符串键,也可以给MyDto添加索引签名,但这种方式会允许任意属性,不推荐用于需要严格类型控制的场景:
export class MyDto { name: string age: number [key: string]: unknown // 添加字符串索引签名 constructor(name: string, age: number) { this.name = name this.age = age } }
问题2:传入MyChildClass实例到useClass时的类型错误
原因
useClass的参数类型MyAbstractClass未指定泛型参数,TypeScript会使用默认泛型类型(原默认值为Record<string, unknown>),而MyChildClass的泛型参数是MyDto,二者类型不兼容导致报错。
解决方案
方案1:泛型函数(推荐,保留类型安全)
让useClass支持泛型,可接受任意MyAbstractClass的子类型:
function useClass<T extends object>(data: MyAbstractClass<T>) { console.log(data) }
方案2:使用MyAbstractClass<any>(简单但丢失类型信息)
这种方式能快速解决错误,但会失去TypeScript的类型检查优势,仅适合不需要类型安全的场景:
function useClass(data: MyAbstractClass<any>) { console.log(data) }
完整修正代码
export class MyDto { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } abstract class MyAbstractClass<T extends object = object> { constructor(public readonly title: string, public readonly data: T) {} } class MyChildClass extends MyAbstractClass<MyDto> { constructor(data: MyDto) { super('user_info', data) } } function useClass<T extends object>(data: MyAbstractClass<T>) { console.log(data) } const instance = new MyChildClass(new MyDto('John', 17)) useClass(instance) // 无类型错误
内容的提问来源于stack exchange,提问作者Willower
相关产品推荐
相关产品推荐

