You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于父类对象属性修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:25:28