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

如何配置TypeScript限制字面量表达式仅接受可用属性?

解决TypeScript中多余属性赋值的编译时检查问题

这个问题的核心在于TypeScript的结构类型系统默认允许多余属性赋值——当赋值源是变量而非直接对象字面量时,TS只会校验目标类型要求的属性是否存在,不会限制额外属性。要解决这个问题,我们可以从编译时检查和运行时约束两个角度入手,下面是几种可行的方案:

方案1:泛型工具函数(编译时+运行时约束)

写一个通用的pick函数,只提取目标类型指定的属性,既在编译时阻止多余属性的类型赋值,又能在运行时移除多余属性。这种方案不管有没有实例对象都适用,只有类型定义时手动传入属性键即可:

// 泛型pick函数:从对象中提取指定键的属性
const pick = <T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> => {
  const result = {} as Pick<T, K>;
  keys.forEach(key => {
    result[key] = obj[key];
  });
  return result;
};

// 示例场景:有实例对象的情况
const foo = { "a" :1, "b" :2, "c" :3 }
const foo2 = { "a":1, "c":2 }
type Foo2Type = typeof foo2;

// 从foo中提取foo2类型的所有属性
const foo3: Foo2Type = pick(foo, ...(Object.keys(foo2) as Array<keyof Foo2Type>));
// foo3仅包含a和c属性,编译时无多余属性报错,运行时也不会有b属性

// 仅定义类型无实例的场景
type TargetType = {a: number; c: number};
const foo4: TargetType = pick(foo, 'a', 'c');

方案2:编译时类型校验(仅检查不修改运行时)

如果只需要在编译时阻止多余属性赋值,不需要运行时移除属性,可以通过自定义交叉类型来实现。这个方案利用Exclude工具类型检测是否存在多余属性:

// 自定义类型:如果U包含T没有的属性,则返回never(触发类型错误)
type ExcessPropertiesError<T, U> = Exclude<keyof U, keyof T> extends never ? U : never;

const foo = { "a" :1, "b" :2, "c" :3 }
type Foo2Type = {a: number; c: number}; // 仅类型定义,无实例

// 交叉类型会在foo包含Foo2Type以外的属性时报错
const foo3: Foo2Type & ExcessPropertiesError<Foo2Type, typeof foo> = {...foo};
// 此时TS会抛出类型错误:类型"{ a: number; b: number; c: number; }"不能赋值给类型"Foo2Type & never"

为什么原代码不报错?

补充说明一下:当你直接用对象字面量赋值给Foo2Type时,TS会触发多余属性检查(比如const foo3: Foo2Type = {a:1, c:2, b:3}会报错),但当赋值源是变量(比如...foo)时,TS的结构类型系统会认为变量可能是动态生成的,因此默认允许多余属性存在。上面的方案就是专门针对这种场景做的约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:35:19