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

为何TypeScript中扩展语法(...)不遵循返回类型的类型安全性?

问题解析:扩展语法添加非法键未触发TypeScript报错

核心原因:不是Bug,是类型检查机制差异

你遇到的情况是TypeScript的设计行为——关键在于TypeScript对「直接对象字面量」和「扩展语法组合的对象」采用了不同的检查规则:

  1. 直接对象字面量会触发「多余属性检查」
    当你直接在返回的对象字面量里写wut: 'somewut'时,TypeScript会启动专门针对对象字面量的额外校验:如果字面量包含目标类型(这里是Partial<Record<Value, string>>)中未定义的属性,就会抛出错误。这是TypeScript为避免拼写错误或意外添加属性设计的保护机制。

  2. 扩展语法不会触发多余属性检查
    当你用...({wut: 'somewut'})时,被扩展的{wut: 'somewut'}是一个独立表达式,TypeScript会先将其推断为普通的{wut: string}类型。这个类型和前面的对象合并后,得到Partial<Record<Value, string>> & {wut: string}类型。

    而TypeScript的结构类型系统允许子类型赋值给父类型——合并后的类型包含了目标类型的所有属性,还多了wut,属于目标类型的子类型,因此编译器认为它可以安全赋值给返回类型,不会报错。

解决方案:强制限制扩展对象的类型

如果你想让编译器检测到这类非法属性,可以显式约束被扩展对象的类型,比如:

方案1:使用satisfies关键字(TypeScript 4.9+)

type Value = 'foo'| 'bar'| 'baz';

const getValues = (): Partial<Record<Value, string>> => {
    return {
        foo: 'someFoo',
        baz: 'someBaz',
        ...({wut: 'somewut'} satisfies Partial<Record<Value, string>>)
    }
}

编译器会直接检查被扩展对象是否符合目标类型,非法属性会立刻报错。

方案2:类型断言(兼容旧版本)

type Value = 'foo'| 'bar'| 'baz';

const getValues = (): Partial<Record<Value, string>> => {
    return {
        foo: 'someFoo',
        baz: 'someBaz',
        ...({wut: 'somewut'} as Partial<Record<Value, string>>)
    }
}

通过断言指定被扩展对象的类型,非法属性会触发断言错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:33:26