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

TypeScript中如何通过keyof获取接口指定类型的键?

问题:如何从TypeScript接口中仅提取指定类型字段的键?

首先看简化后的接口和示例对象:

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

const person: Person = {
  name: 'Yair',
  address: 'here',
  age: 12,
  height: 186
};

需求是创建函数动态更新name/address这类字符串类型字段,直接指定联合类型"name"|"address"可以正常运行:

let updateNameOrAddress = (key: "name"|"address", value: string): void => {
  person[key] = value;
};

但随着字符串类型字段增多,这种写法会非常繁琐。尝试用keyof Person替代时出现类型错误:

let updateNameOrAddress = (key: keyof Person, value: string): void => {
  person[key] = value; // 错误:Type 'string' is not assignable to type 'never'
};

错误原因是keyof Person包含了age/height这类数字类型的键,TypeScript无法保证string类型的value能匹配所有可能的字段类型,因此抛出报错。


解决方案

可以通过TypeScript的条件类型定义工具类型,精准筛选出接口中字段类型为指定类型的键。

1. 定义工具类型提取目标键

// 提取接口中字段类型为string的键
type StringKeys<T> = {
  [K in keyof T]: T[K] extends string ? K : never;
}[keyof T];

// 同理,提取数字类型字段的键可写为:
// type NumberKeys<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T];

2. 基于工具类型编写更新函数

用StringKeys<Person>作为key的类型,自动筛选出name/address,同时保证value类型匹配:

let updateNameOrAddress = (key: StringKeys<Person>, value: string): void => {
  person[key] = value; // 类型检查通过,无报错
};

// 测试示例:
updateNameOrAddress('name', 'NewName'); // 合法
updateNameOrAddress('address', 'NewAddress'); // 合法
// updateNameOrAddress('age', 20); // 报错:"age"不属于合法key范围

3. 通用化更新函数(可选)

如果需要支持任意字段的类型安全更新,可以写一个泛型函数,自动根据key推断value类型:

function updateField<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
  obj[key] = value;
}

// 调用示例:
updateField(person, 'name', 'Yair Updated'); // 合法
updateField(person, 'age', 13); // 合法
// updateField(person, 'name', 123); // 报错:number类型无法赋值给string字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:40:28