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

TypeScript如何根据属性类型添加可选属性?

解决TypeScript中根据actionType动态添加属性的问题

你的问题出在当前的联合类型定义上:Creator 是 CreatorBase 和 CreatorSwim 的联合,但 CreatorBase 包含了所有 ActionType(包括FIGHT和DANCE),TypeScript无法确定你访问的对象是不是带有trained属性的CreatorSwim,所以直接访问会报错。

下面是两种可行的解决方式:

方式一:拆分判别式联合类型

把不同actionType对应的类型分开定义,形成判别式联合,TypeScript会通过actionType自动窄化类型:

const FIGHT = `fight`;
const SWIM = `swim`;
const DANCE = `dance`;

type ActionType = typeof FIGHT | typeof SWIM | typeof DANCE;

interface CreatorBase {
  typeId: string;
}

interface FightCreator extends CreatorBase {
  actionType: typeof FIGHT;
}

interface SwimCreator extends CreatorBase {
  actionType: typeof SWIM;
  trained?: string;
}

interface DanceCreator extends CreatorBase {
  actionType: typeof DANCE;
}

export type Creator = FightCreator | SwimCreator | DanceCreator;

使用时,通过判断actionType就能安全访问trained:

function processCreator(creator: Creator) {
  if (creator.actionType === SWIM) {
    // 这里类型已窄化为SwimCreator,可直接访问trained
    console.log(creator.trained);
  }
}

方式二:使用条件类型动态生成接口

通过条件类型,根据传入的actionType决定是否包含trained属性:

const FIGHT = `fight`;
const SWIM = `swim`;
const DANCE = `dance`;

type ActionType = typeof FIGHT | typeof SWIM | typeof DANCE;

type Creator<T extends ActionType = ActionType> = {
  actionType: T;
  typeId: string;
} & (T extends typeof SWIM ? { trained?: string } : {});

// 使用示例
const swimCreator: Creator<typeof SWIM> = {
  actionType: SWIM,
  typeId: "swim_001",
  trained: "半年"
};

const fightCreator: Creator<typeof FIGHT> = {
  actionType: FIGHT,
  typeId: "fight_001"
  // 此处添加trained会触发类型错误,符合预期
};

// 不指定泛型时,为所有类型的联合
const randomCreator: Creator = {
  actionType: DANCE,
  typeId: "dance_001"
};

内容的提问来源于stack exchange,提问作者Mad-D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:32:36