如何基于父类对象属性修改TypeScript子类的参数类型?
问题描述
我在项目中定义了ParentClass和继承它的ChildrenClass,ParentClass的实现代码如下:
interface ConfObj<T extends boolean> { enabled: T; permissions: bigint[]; location: string; } interface HelpObj { name: string; description: string category: string; id: number; } interface ParentClassType<T extends boolean> { conf: ConfObj<T>; help: HelpObj; } type ParentClassParameters<T extends boolean> = HelpObj & ConfObj<T>; class ParentClass<T extends boolean> { conf: ConfObj<T>; help: HelpObj; constructor({ enabled, permissions, location, name, description, category, id }: ParentClassParameters<T>) { this.conf = { enabled, permissions, location }; this.help = { name, description, category, id } } }
我需要根据ParentClass.conf.enabled的取值,调整ChildrenClass中run方法参数的类型:
- 当
enabled为true时,参数的description类型限定为string - 当
enabled为false时,description类型为string | undefined
我尝试了以下ChildrenClass代码,但run方法存在类型错误,要求在不添加条件判断或修改返回类型的前提下解决问题:
interface AChildrenParameterInterface<T extends ParentClass<any>> { isEnabled: () => boolean; name: string; description: string | (T["conf"]["enabled"] extends false ? undefined : never); } class ChildrenClass extends ParentClass<true> { constructor() { super({ enabled: true, permissions: [], location: '', name: '', description: '', category: '', id: 0 }); } run(data: AChildrenParameterInterface<ChildrenClass>) { return data.description; } }
解决方案
问题核心在于原AChildrenParameterInterface的泛型约束T extends ParentClass<any>会丢失enabled的具体布尔类型信息,导致TypeScript无法正确推断description的类型。以下是两种可行的修正方案:
方案一:直接绑定布尔泛型
让参数接口直接接收布尔类型泛型,明确关联enabled的取值:
interface AChildrenParameterInterface<T extends boolean> { isEnabled: () => boolean; name: string; description: T extends true ? string : string | undefined; } class ChildrenClass extends ParentClass<true> { constructor() { super({ enabled: true, permissions: [], location: '', name: '', description: '', category: '', id: 0 }); } run(data: AChildrenParameterInterface<this["conf"]["enabled"]>) { return data.description; } }
方案二:从父类实例提取enabled类型
如果希望接口保持接收ParentClass类型,可以通过条件类型提取enabled的具体值:
type ExtractEnabled<T extends ParentClass<any>> = T["conf"]["enabled"]; interface AChildrenParameterInterface<T extends ParentClass<any>> { isEnabled: () => boolean; name: string; description: ExtractEnabled<T> extends true ? string : string | undefined; } class ChildrenClass extends ParentClass<true> { constructor() { super({ enabled: true, permissions: [], location: '', name: '', description: '', category: '', id: 0 }); } run(data: AChildrenParameterInterface<ChildrenClass>) { return data.description; } }
修正逻辑说明
原写法中,T["conf"]["enabled"] extends false ? undefined : never的表达式因ParentClass<any>的any擦除了类型信息,TypeScript无法识别ChildrenClass对应的enabled是true,进而无法正确解析description的类型。通过直接绑定布尔泛型或提取具体的enabled类型,TypeScript可以准确匹配description的类型约束,解决类型错误。
内容的提问来源于stack exchange,提问作者Pioupia
相关产品推荐
相关产品推荐

