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

TypeScript约束对象符合指定类型且保留精确类型推断的方法

TypeScript 实现严格结构约束+精确类型推断方案

实现思路

要同时满足「符合目标结构、禁止多余属性、精确推断实际属性」三个要求,不能直接用类型注解、普通泛型约束或者satisfies运算符——前两种会把类型放宽到目标类型,导致未声明的可选属性可访问;普通泛型约束和satisfies仅做子类型兼容校验,不会拦截额外属性。
正确方案是通过递归映射类型实现精确结构匹配校验,配合泛型恒等函数完成类型推断。

完整实现代码

// 目标类型(已定义的TypeA)
type TypeA = {
    a: number;
    b: {
        c: number;
        d?: string;
        e?: boolean;
    }
}

// 递归精确校验工具类型:保证T严格匹配Shape结构,不存在Shape外的多余属性
type Exact<T, Shape> = T extends Shape
  ? {
      [K in keyof T]: K extends keyof Shape
        ? Exact<T[K], Shape[K]>
        : never;
    }
  : never;

// 受约束的构建函数
function buildTypeA<T extends TypeA>(obj: T & Exact<T, TypeA>) {
  return obj;
}

实际效果

合法场景(正常通过,类型精确收窄)

传入示例中的对象:

const myObj = buildTypeA({
    a: 1,
    b: {
        c: 2,
        d: 'hello',
    }
});

此时TS推断出的myObj类型完全和传入的结构一致:

  • 可正常访问已声明的a、b.c、b.d属性,类型完全匹配
  • 访问未声明的b.e时,TS会直接抛出「Property 'e' does not exist on type」的错误,完全符合预期。

非法场景(直接触发类型报错)

以下不符合要求的写法都会被TS拦截:

  • 顶层新增TypeA未定义的属性:
const badCase1 = buildTypeA({
  a: 1,
  b: { c: 2 },
  extraProp: 123 // ❌ 类型错误:number不能赋值给never
})
  • 嵌套对象内新增未定义属性:
const badCase2 = buildTypeA({
  a: 1,
  b: {
    c: 2,
    extraNested: 'test' // ❌ 类型错误:多余属性不允许
  }
})
  • 缺失必填属性(比如漏写a、b.c),会正常触发必填属性缺失的报错。

注意点

  • 该工具类型是递归实现的,支持任意深度的嵌套对象校验,不会遗漏深层结构的多余属性
  • 如果显式传入了可选属性(比如e: true或e: undefined),该属性会被加入最终推断类型,访问不会报错,符合代码实际逻辑
  • 对于其他需要相同约束的类型,直接复用Exact工具类型写对应构建函数即可,无需重复实现校验逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:57:39