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

TypeScript如何同时实现对象字面量严格校验与类型提取?

实现TypeScript严格属性校验与精确字面量类型提取

现有TypeScript类型定义:

type MyType = {
  A: number | string
}

当前存在两种不可兼得的场景:

  • 直接给标注MyType的变量赋值时,额外属性会触发类型错误(符合预期),但变量类型被收窄为MyType,无法保留字面量的精确类型;
  • 直接定义对象字面量再用typeof提取类型,能得到精确的字面量类型,但无法在赋值阶段校验是否符合MyType的结构。

需求是同时达成两点:

  1. 赋值时严格校验,禁止超出MyType的额外属性;
  2. 提取对象字面量的精确类型(如{A: number}),无需额外定义第二个类型。

解决方案:用泛型工具实现双目标

可以通过泛型工具类型或泛型函数,同时实现严格属性校验和精确类型保留:

方式一:泛型类型约束

type StrictAssign<T, U extends T> = U & {
  [K in Exclude<keyof U, keyof T>]?: never
};

// 正确赋值,保留精确类型
const myValue: StrictAssign<MyType, typeof myValue> = {
  A: 123
};
type MyExactType = typeof myValue; // 类型为 {A: number}

// 额外属性触发错误
const invalidValue: StrictAssign<MyType, typeof invalidValue> = {
  A: 123,
  B: "Oh!" // 类型错误:额外属性B不符合约束
};

方式二:泛型函数(更直观)

function createStrictValue<T>(value: T & { [K in Exclude<keyof typeof value, keyof T>]?: never }) {
  return value;
}

// 正确赋值,自动推导精确类型
const myValue = createStrictValue<MyType>({
  A: 123
});
type MyExactType = typeof myValue; // {A: number}

// 额外属性直接报错
const invalidValue = createStrictValue<MyType>({
  A: 123,
  B: "Oh!" // 类型错误:对象字面量只能指定MyType中的已知属性
});

原理说明

  • U extends T(或函数中T作为泛型参数)确保赋值的对象符合MyType的结构要求;
  • { [K in Exclude<keyof U, keyof T>]?: never }通过约束额外属性的类型为never,让字面量中的额外属性无法通过类型检查;
  • 最终变量的类型是对象字面量的精确类型U,而非宽泛的MyType,保留了具体的属性值类型(比如number而非number | string)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:12:34