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

TypeScript:Partial的更优替代方案——Partial存在类型不安全问题

Partial类型的类型安全问题及替代方案

我发现Partial的表现出乎意料,它似乎并不具备类型安全性。在如下代码示例中,将Partial<A>类型的变量b展开后赋值给C类型的变量c时未触发错误,但直接为c添加b属性却报错:

type A = {
    a: string;
    b: string;
}

type B = Partial<A>

type C = {
    a: string;
    d: string;
}

let b: B = { b: 'b'};


const c: C = {
    d: 'd',
    a: 'a',
    ...b, // 无错误...这是为什么?
}

const cc: C = {
    d: 'd',
    a: 'a',
    b: 'b' // 报错
}

原因说明

这是TypeScript对象展开的类型检查逻辑导致的:当展开Partial类型对象时,TS会默认认为额外属性要么是可选的,要么会被后续属性覆盖,因此不会严格校验是否完全匹配目标类型;而直接显式添加不属于目标类型的字面量属性时,会触发严格的字面量类型检查,所以报错。

替代方案

  • 精准筛选属性:手动或用类型约束只保留目标类型允许的属性,避免引入额外字段:
    // 手动筛选
    const filteredB = { a: b.a };
    const c: C = {
      d: 'd',
      a: 'a',
      ...filteredB
    };
    
    // 用Pick类型约束可继承的属性
    type AllowedFromA = Pick<A, keyof C & keyof A>; // 仅保留A和C共有的a属性
    const c: C = {
      d: 'd',
      a: 'a',
      ...(b as AllowedFromA)
    };
    
  • 定义严格的部分类型:创建仅包含目标类型允许属性的Partial变体,从源头避免额外属性:
    type SafePartialForC = Partial<Pick<A, keyof C>>;
    let b: SafePartialForC = { a: 'newA' }; // 无法赋值b属性,因为C不包含该字段
    const c: C = {
      d: 'd',
      a: 'a',
      ...b
    };
    
  • 用工具函数清理额外属性:写一个通用函数,自动剔除目标类型以外的属性:
    function keepOnlyAllowedProps<T>(obj: any): Partial<T> {
      const result: Partial<T> = {};
      Object.keys(obj).forEach(key => {
        if (key in result) {
          result[key as keyof T] = obj[key];
        }
      });
      return result;
    }
    
    const c: C = {
      d: 'd',
      a: 'a',
      ...keepOnlyAllowedProps<C>(b)
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:57:28