【TypeScript】泛型约束

泛型约束

有一个这样的代码

function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: "Alice", age: 30 };
const name = getValue(user, "name"); // string
const age = getValue(user, "age"); // number

为什么 K 可以 extends keyof T ?keyof T 是接口吗?

在 TypeScript 中,K extends keyof T 是一个泛型约束,它表示类型参数 K 必须是 T 类型的所有可能键名的联合类型的子类型。我来详细解释这个概念:

1. keyof T 是什么?

  • keyof T 是一个索引类型查询操作符,它会返回 T 类型的所有公共属性名的联合类型
  • 如果 T 是一个接口或对象类型,keyof T 就是它的所有键名的字符串字面量联合类型

示例:

interface Person {
  name: string;
  age: number;
}

type PersonKeys = keyof Person; 
// 等同于: "name" | "age"

2. K extends keyof T 的含义

  • 这里的 extends 表示泛型约束,不是类继承
  • 它限制 K 只能是 keyof T 的子集(即只能是 T 的合法属性名)
  • 这样就能保证 obj[key] 的访问是类型安全的

3. 为什么可以这样写?

  • TypeScript 的类型系统允许这种约束
  • keyof T 本身就是一个类型(联合类型)
  • extends 在泛型中表示"必须是…的子类型"

4. 实际应用示例

function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person = { name: "Alice", age: 30 };

// 正确 - "name" 是 Person 的键
const name = getValue(person, "name"); // string 类型

// 正确 - "age" 是 Person 的键 
const age = getValue(person, "age"); // number 类型

// 错误 - "gender" 不是 Person 的键
const gender = getValue(person, "gender"); // 编译时报错

5. 与接口的关系

  • keyof T 不是接口,而是一个类型操作符
  • T 是接口时,keyof T 会生成该接口所有属性的联合类型
  • T 也可以是其他类型,如:
    type TupleKeys = keyof [string, number]; // "0" | "1" | "length" | ...
    

这种设计提供了强大的类型安全性,确保:

  1. 只能访问对象实际存在的属性
  2. 返回值类型与属性类型精确匹配
  3. 在编译时就能捕获拼写错误或无效的属性访问
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值