TypeScript如何同时实现对象字面量严格校验与类型提取?
实现TypeScript严格属性校验与精确字面量类型提取
现有TypeScript类型定义:
type MyType = { A: number | string }
当前存在两种不可兼得的场景:
- 直接给标注
MyType的变量赋值时,额外属性会触发类型错误(符合预期),但变量类型被收窄为MyType,无法保留字面量的精确类型; - 直接定义对象字面量再用
typeof提取类型,能得到精确的字面量类型,但无法在赋值阶段校验是否符合MyType的结构。
需求是同时达成两点:
- 赋值时严格校验,禁止超出
MyType的额外属性; - 提取对象字面量的精确类型(如
{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
相关产品推荐
相关产品推荐

