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

TypeScript:如何依据对象的兄弟属性推断对象类型?

如何基于对象的type属性推断value的具体类型

首先,我们来分析你当前代码的问题:你定义的steps类型是Record<string, Step>,而这里的Step因为没有指定具体的泛型参数,会默认使用Step<StepKeys>,这导致每个step的type是"Test1" | "Test2"的联合类型,value是{name: string} | {age: number}的联合类型。TypeScript无法将type和value的具体值关联起来,所以既不会在赋值时做严格的类型检查,也没法在后续使用时根据type推断value的类型。

下面提供两种实用的解决方案,让TypeScript能够正确关联type和value的类型:

方案一:使用可区分联合类型(Discriminated Unions)

直接把Step定义为一个可区分联合类型,让type作为类型区分符,这样TypeScript能自动绑定type和value的对应关系:

type StepKeys = "Test1" | "Test2";

interface objectMap {
    "Test1": { name: string },
    "Test2": { age: number }
};

// 通过映射类型生成强绑定的可区分联合类型
type Step = {
    [K in StepKeys]: {
        type: K;
        value: objectMap[K];
    }
}[StepKeys];

// 现在steps的每个成员都会被严格检查type和value的匹配性
const steps: Record<string, Step> = {
    "Step1": {
        type: "Test1",
        value: { name: "Alice" } // 必须包含name属性,少写会直接报错
    },
    "Step2": {
        type: "Test2",
        value: { age: 30 } // 必须包含age属性,类型不匹配也会报错
    }
};

// 使用时通过type自动推断value类型
function processStep(step: Step) {
    if (step.type === "Test1") {
        console.log(`Name: ${step.value.name}`); // 这里step.value的类型是{name: string}
    } else {
        console.log(`Age: ${step.value.age}`); // 这里step.value的类型是{age: number}
    }
}

这种方式是TypeScript处理这类关联类型场景的标准做法,既能保证类型安全,又能获得精准的类型推断。

方案二:让TypeScript自动推断类型(无需显式指定steps类型)

如果你不需要强制steps的所有成员都严格符合Step结构,或者希望更灵活的类型推导,可以去掉steps的类型注解,让TypeScript自动识别每个成员的具体类型:

type StepKeys = "Test1" | "Test2";

interface objectMap {
    "Test1": { name: string },
    "Test2": { age: number }
};

interface Step<T extends StepKeys = StepKeys> {
    type: T;
    value: objectMap[T]
};

// 去掉类型注解,让TypeScript自动推断每个step的精确类型
const steps = {
    "Step1": {
        type: "Test1",
        value: { name: "Bob" }
    },
    "Step2": {
        type: "Test2",
        value: { age: 25 }
    }
};

// 此时访问steps.Step1.value时,TypeScript明确知道它是{name: string}类型
console.log(steps.Step1.value.name); // 完全符合类型检查
console.log(steps.Step2.value.age); // 不会出现类型报错

如果需要进一步锁定字面量类型,让推断更精准,可以加上as const:

const steps = {
    "Step1": {
        type: "Test1",
        value: { name: "Bob" }
    },
    "Step2": {
        type: "Test2",
        value: { age: 25 }
    }
} as const;

这样steps.Step1.type会被推断为字面量"Test1",而不是模糊的StepKeys联合类型,对应的value类型也会被精确锁定。

总结

核心思路是让TypeScript识别type与value的关联关系:

  • 使用可区分联合类型是最规范的方案,适合需要严格类型约束的生产场景;
  • 自动推断类型则更灵活,适合快速原型开发或结构不固定的场景。

内容的提问来源于stack exchange,提问作者hyperdrive

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:45:28