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

TypeScript扩展类型展开时多余属性保留的解决方法问询

TypeScript中如何过滤继承类型的额外属性

当把继承自B的类型A的对象展开到标注为B类型的变量时,TypeScript的编译时类型检查不会在运行时自动剔除A中额外的属性,导致输出仍然包含所有属性。比如:

interface B {
  name: string;
}

interface A extends B {
  age: number;
}

const fullThing: A = { age: 21, name: 'Bob' };

const thing: B = { ...fullThing };

console.log(thing); // 输出 { "age": 21, "name": "Bob" }

想要得到仅包含B类型属性的输出:{ "name": "Bob" },可以用以下几种方法:


方法1:手动提取目标属性

直接解构出B中定义的属性,适合属性数量少的场景:

// 直接赋值
const thing: B = { name: fullThing.name };

// 或者用对象解构简化
const { name } = fullThing;
const thing: B = { name };

方法2:写通用过滤函数

如果B的属性较多,可以封装一个工具函数,传入目标对象和需要保留的属性列表来过滤:

function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  const result = {} as Pick<T, K>;
  keys.forEach(key => {
    if (key in obj) {
      result[key] = obj[key];
    }
  });
  return result;
}

// 使用时传入B的属性键
const thing: B = pick(fullThing, ['name']);
console.log(thing); // { "name": "Bob" }

方法3:结合类型系统增强安全性

为了避免手动写错属性名,可以基于B类型定义一个受类型检查的属性键数组,再用它来过滤:

// 定义B的属性键数组,TypeScript会自动校验元素是否为B的合法属性
const BKeys = ['name'] as const satisfies readonly (keyof B)[];

function pickFrom<T, K extends readonly (keyof T)[]>(obj: T, keys: K): Pick<T, K[number]> {
  const result = {} as Pick<T, K[number]>;
  (keys as readonly string[]).forEach(key => {
    if (key in obj) {
      result[key as keyof T] = obj[key];
    }
  });
  return result;
}

const thing: B = pickFrom(fullThing, BKeys);
console.log(thing); // { "name": "Bob" }

注意:TypeScript是编译时类型检查工具,运行时不存在类型信息,因此必须通过代码逻辑手动过滤属性,类型标注仅用于编译时校验,不会改变运行时对象的实际结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:53:22