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

TypeScript泛型推断时如何限制对象仅允许指定键?

在TypeScript中约束泛型对象仅允许已知键

要实现你期望的「传入含额外键的对象时函数报错」的效果,需要手动添加精确类型约束——因为TypeScript的结构子类型系统默认允许子类型包含额外属性,泛型T extends Data会直接推断出包含额外键的类型(比如{a:number; b:number; c:number}),而这个类型确实符合extends Data的条件,所以不会报错。

解决方案:自定义Exact工具类型

可以通过自定义工具类型Exact强制泛型T的键只能是目标类型的已知键:

type Data = {
    a: number;
    b: number;
};

// 工具类型:约束T的键完全匹配Base的键,不允许额外属性
type Exact<Base, T> = 
  T extends Base 
    ? Exclude<keyof T, keyof Base> extends never 
      ? T 
      : never 
    : never;

// 使用Exact约束泛型T
function foo<T extends Exact<Data, T>>(o: T) {}

foo({a:8,b:4,c:8}) // 报错:类型"{ a: number; b: number; c: number; }"不满足约束"Exact<Data, { a: number; b: number; c: number; }>"
foo({a:8,b:4}) // 正常通过

原理说明

  • Exact<Base, T>先检查T是否是Base的子类型;
  • 再通过Exclude<keyof T, keyof Base>判断T是否包含Base没有的键:如果有,结果不为never,则Exact返回never,导致泛型约束不通过,触发报错;
  • 只有当T的键完全等于Base的键时,Exact才会返回T,允许函数调用。

简洁写法:直接在泛型约束中检查

如果不想单独定义工具类型,也可以直接在函数的泛型约束中合并检查逻辑:

function foo<T extends Data>(o: T & (Exclude<keyof T, keyof Data> extends never ? {} : never)) {}

foo({a:8,b:4,c:8}) // 同样会触发报错

注意事项

  • 当传入一个预先定义好的变量(而非直接传入字面量)时,只要变量类型包含额外键,同样会触发报错;
  • 如果将含额外键的变量断言为Data类型,函数调用不会报错(因为断言后的类型已经丢失了额外键信息)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:16:12