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
相关产品推荐
相关产品推荐

