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

TypeScript中为何用extends keyof约束泛型而非in keyof?

在TypeScript中声明带约束的泛型类型参数时,为何使用“extends keyof”而非“in keyof”?

在TypeScript官网的泛型章节中,extends在声明类型参数时有两种典型用法:

1. 基础泛型约束

通过extends让泛型参数继承某个接口,确保其拥有指定的属性或方法:

interface Lengthwise {
  length: number;
}
 
function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
  console.log(arg.length);
  return arg;
}

2. 用其他类型参数约束当前参数

用extends keyof限定泛型参数必须是另一个类型的键:

function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) {
  return obj[key];
}
 
let x = { a: 1, b: 2, c: 3, d: 4 };
 
getProperty(x, "a"); // 合法
getProperty(x, "m"); // 报错:类型'"m"'不能赋值给类型'"a" | "b" | "c" | "d"'

第一种用法符合OOP继承逻辑很好理解,但第二种场景中,为什么用extends keyof而不用映射类型里的in keyof?比如映射类型的示例:

type Optional<T> = {
    [K in keyof T]?: T[K];
};

核心原因:两者的语法定位和作用完全不同

  • extends是类型约束语法:它的作用是限定泛型参数的取值范围,要求泛型参数必须是目标类型的子类型。在Key extends keyof Type中,keyof Type会生成一个由Type所有键组成的联合类型,extends则要求Key必须是这个联合类型的子集(可以是单个键,也可以是多个键组成的子联合类型),以此约束传入的key参数必须是obj的合法键。

  • in是映射遍历语法:它只能用于对象类型的属性定义中,作用是遍历一个联合类型的所有成员,为每个成员生成对应的属性。比如[K in keyof T]会遍历T的所有键,把每个键K都转换成新对象的可选属性,这是用来构建新类型的语法,根本不能用于泛型参数的约束场景——TypeScript的语法规则不允许在泛型参数声明中使用in。

简单来说,extends keyof是用来“限制单个参数的合法类型”,而in keyof是用来“批量生成对象属性”,两者的应用场景没有交集,自然不能混用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:45:55