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

如何编写TypeScript泛型函数获取继承HasID接口的对象属性?

解决TypeScript泛型函数校验对象属性是否继承HasID的问题

我来帮你搞定这个需求!你想要实现一个泛型函数,只有当传入的对象属性符合HasID接口时才允许调用,否则报错。你的思路是对的,但原来的类型约束写法有问题,导致TypeScript无法正确推断O[K]和T的关系,所以出现了赋值错误。

下面是正确的实现方案,我会一步步拆解说明:

第一步:定义基础接口和辅助类型

首先保留你的HasID接口,然后我们需要一个辅助类型来提取对象中属性类型符合HasID的键:

interface HasID { id: number; }

// 辅助类型:筛选出对象O中属性类型继承HasID的所有键
type KeysWithID<O> = { 
  [K in keyof O]: O[K] extends HasID ? K : never 
}[keyof O];

这个辅助类型的逻辑是:遍历对象O的每个键K,如果对应的属性O[K]是HasID的子类型,就保留键K,否则标记为never;最后通过[keyof O]把所有有效的键提取出来,形成一个联合类型。

第二步:实现泛型get函数

接下来用这个辅助类型约束函数的泛型参数,这样就能自动校验传入的键是否合法:

function get<O extends object, K extends KeysWithID<O>>(obj: O, key: K): O[K] {
  return obj[key];
}

这里的泛型参数O是输入对象的类型,K被约束为KeysWithID<O>——也就是说,只有那些对应属性符合HasID的键才能被传入。返回类型直接用O[K],因为TypeScript已经知道这个属性必然是HasID的子类型,不需要额外的T参数。

测试用例验证

现在来测试你的示例场景,完全符合预期:

let obj = { foo: 123, bar: { id: 123 }, baz: { id: 'abc' } };

get(obj, 'foo'); // ❌ 类型错误:"foo"对应的属性是数字,不符合HasID
get(obj, 'bar'); // ✅ 正常运行,返回类型是{ id: number; }
get(obj, 'baz'); // ❌ 类型错误:baz的id是字符串,不符合HasID的number类型要求

解释你原来的问题

你之前的HasPropertyWithID接口定义有问题:类型参数K不能直接作为属性名使用(应该用映射类型或索引签名),而且泛型参数的顺序和约束逻辑没有建立起O[K]和T的明确关联,导致TypeScript无法确认obj[key]的类型就是T,所以抛出了赋值错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:45:17