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

TypeScript类型识别疑问:为何未检测到属性缺失错误?

问题

定义常量时指定了TT类型,但TypeScript未抛出预期错误:常量C同时包含number_:'N'和string_:'S'属性,且缺少valueN,但并未触发报错。代码示例如下:

// example
type TT = string | {string_:'S', valueS:string} | {number_:'N', valueN:number};

function run(p:TT):number{
    if(typeof p === 'string'){
        throw '';
    }
    if('number_' in p){
        return p.valueN;
    }
    throw '';
}

const C:TT = {number_:'N',string_:'S',valueS:'text'};

console.log(run(C));
原因解释

TypeScript采用结构类型系统,联合类型的检查逻辑是:只要值符合联合类型中至少一个成员的结构要求,就会被认为属于该联合类型。

你的代码里,常量C的结构{number_:'N',string_:'S',valueS:'text'}完全匹配TT中的{string_:'S', valueS:string}成员——虽然多了number_:'N'属性,但TypeScript默认允许对象存在额外属性(除非开启严格的额外属性检查或使用精确类型约束)。因此TypeScript判定C属于TT类型,不会抛出缺少valueN的错误。

当run函数处理C时,'number_' in p检查为真,函数会尝试返回p.valueN,但该属性不存在,最终会在运行时抛出错误。

改进方案

方案1:使用互斥属性的可辨识联合

修改TT类型,为每个对象成员添加互斥的可选never类型属性,确保对象只能符合联合类型中的一个成员:

type TT = 
  string | 
  {string_:'S', valueS:string, number_?: never} | 
  {number_:'N', valueN:number, string_?: never};

function run(p:TT):number{
    if(typeof p === 'string'){
        throw '';
    }
    if('number_' in p){
        return p.valueN;
    }
    throw '';
}

// 此时会报错:类型 "{ number_: 'N'; string_: 'S'; valueS: string; }" 不能分配给类型 "TT"
const C:TT = {number_:'N',string_:'S',valueS:'text'};

方案2:使用satisfies操作符(TypeScript 4.9+)

satisfies操作符会先推断常量的实际类型,再检查是否符合目标类型,同时保留常量的具体类型信息,且不允许额外属性导致的类型不匹配:

type TT = string | {string_:'S', valueS:string} | {number_:'N', valueN:number};

function run(p:TT):number{
    if(typeof p === 'string'){
        throw '';
    }
    if('number_' in p){
        return p.valueN;
    }
    throw '';
}

// 此时会报错:类型 "{ number_: 'N'; string_: 'S'; valueS: string; }" 不满足类型 "TT"
const C = {number_:'N',string_:'S',valueS:'text'} satisfies TT;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:25:16