基于递归泛型接口定义TypeScript的GraphNode抽象基类
修复方案
完整可运行代码
type Literal = null | boolean | number | string; type LiteralAttributes<Base> = { [Key in keyof Base]: Base[Key] extends Literal ? Base[Key] : never; }; type RefAttributes<Base> = { [Key in keyof Base]: Base[Key] extends infer Child ? Child extends GraphNode<any> | null ? Child | null : never : never; }; type GraphAttributes = {[key: string]: Literal | GraphNode<any> | null}; abstract class GraphNode<Attributes extends GraphAttributes> { public attributes = {} as Attributes; public get<K extends keyof LiteralAttributes<Attributes>>(key: K): Attributes[K] { return this.attributes[key]; } public set<K extends keyof LiteralAttributes<Attributes>>(key: K, value: Attributes[K]): this { this.attributes[key] = value; return this; } public getRef<K extends keyof RefAttributes<Attributes>>(key: K): Attributes[K] | null { return this.attributes[key]; } public setRef<K extends keyof RefAttributes<Attributes>>(key: K, value: Attributes[K] | null): this { this.attributes[key] = value; return this; } } // 示例子类 interface IPerson { name: string; age: number; friend: Person; pet: Pet; } interface IPet { type: 'dog' | 'cat'; name: string; } class Person extends GraphNode<IPerson> {} class Pet extends GraphNode<IPet> {}
核心修改说明
- 修复
RefAttributes类型判断逻辑:将Child extends GraphNode改为Child extends GraphNode<any>,允许匹配任意泛型参数的GraphNode子类,解决泛型参数缺失的编译报错。 - 修正
GraphAttributes定义:将属性值允许的GraphNode类型改为GraphNode<any>,符合TypeScript对泛型类型的使用要求。 - 调整
attributes类型断言:直接断言为泛型传入的Attributes类型,无需拆分为字面量属性和引用属性的联合类型,基类内部跳过严格校验,同时保证子类调用类方法时的类型推导完全正确。 - 所有类方法的返回值类型会基于
Attributes自动推导,不会再出现类型信息缺失的报错。
验证效果
使用示例中的用法测试时,类型校验完全符合预期:
- 调用
set方法传入引用类型的键(如pet、friend)时会触发类型错误 - 调用
setRef方法传入字面量类型的键时会触发类型错误 - 所有子类的属性、方法参数都具备严格的类型校验
内容的提问来源于stack exchange,提问作者Don McCurdy
相关产品推荐
相关产品推荐

