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

当data.type为已知值时,如何为TypeScript对象指定类型?

解决方案:基于可区分联合类型的自动类型推断

你已经定义了可区分联合类型(SmsPayload | EmailPayload),这类类型共享一个用于区分的字段type,TypeScript可以利用这个特性,结合条件判断自动推断具体类型。以下是具体实现方式:

方式一:直接通过字面量判断实现自动类型推断

不需要额外定义工具函数,直接在条件分支中检查type字段的值,TS会自动缩小类型范围:

const payload = '{"type":"sms","destination":123}'

type PayloadType = 'sms' | 'email'

interface BasePayload {
    type: PayloadType
}

interface SmsPayload extends BasePayload {
    destination: number
}

interface EmailPayload extends BasePayload {
    destination: string
}

// 先将JSON解析结果断言为联合类型
const data = JSON.parse(payload) as SmsPayload | EmailPayload;

// 根据type字段自动推断类型
if (data.type === 'sms') {
    // 此处data被自动推断为SmsPayload,destination是number类型
    console.log(data.destination.toFixed(0));
} else {
    // 此处data被自动推断为EmailPayload,destination是string类型
    console.log(data.destination.includes('@'));
}

方式二:自定义类型守卫函数(适合复杂场景)

如果需要在多处复用类型判断逻辑,可以定义类型守卫函数,明确告诉TS如何判断某个值属于特定类型:

// 定义类型守卫函数
function isSmsPayload(payload: BasePayload): payload is SmsPayload {
    return payload.type === 'sms';
}

function isEmailPayload(payload: BasePayload): payload is EmailPayload {
    return payload.type === 'email';
}

const rawData = JSON.parse(payload) as BasePayload;

if (isSmsPayload(rawData)) {
    // rawData自动推断为SmsPayload
    console.log(rawData.destination.toFixed(0));
} else if (isEmailPayload(rawData)) {
    // rawData自动推断为EmailPayload
    console.log(rawData.destination.includes('@'));
} else {
    throw new Error(`未知的负载类型: ${rawData.type}`);
}

关键说明

  • 核心原理是可区分联合类型:因为SmsPayload和EmailPayload共享type字段,且该字段的取值是互斥的字面量类型,TS可以通过这个字段的值自动缩小类型范围。
  • JSON.parse默认返回any类型,必须通过类型断言(as SmsPayload | EmailPayload或as BasePayload)告诉TS解析后的对象结构,才能触发后续的类型推断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:23:23