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

TypeScript中调用签名与泛型约束的keyof行为问题

这不是TypeScript的bug,是你对泛型约束的设置有误,导致类型推断不符合预期。

问题根源

你修改后的GetV接口中,内部函数的泛型参数K的约束是keyof KV(接口层级的默认泛型KV,即{[K: string]: any}),而非keyof SUBKV。当你显式指定SUBKV为SpecificTypeInformation时,K的约束仍然是宽泛的string,TypeScript会将K推断为string,因此SUBKV[K]会被解析为SpecificTypeInformation[string],也就是所有值的联合类型'bar'|'baz'。

解决方案

有两种更简洁的写法可以满足需求,且无需导出GetV接口:

方案1:调整泛型约束的指向

修改MyLib.d.ts中GetV接口的内部函数泛型约束,让K继承自SUBKV的键而非KV:

// MyLib.d.ts
interface GetV<KV = {[K: string]: any}> {
  <SUBKV extends KV = KV, K extends keyof SUBKV = keyof SUBKV>(options:{ field: K }): SUBKV[K];
}

export function getV: GetV;

此时调用getV<SpecificTypeInformation>({ field: 'foo' }),K会被正确推断为'foo',返回类型为'bar'。

方案2:直接定义泛型函数类型

放弃泛型接口,直接将getV定义为泛型函数,更直观且避免嵌套泛型的混淆:

// MyLib.d.ts
export function getV<KV extends object = { [K: string]: any }, K extends keyof KV>(options: { field: K }): KV[K];

调用方式不变,TypeScript会根据你指定的KV类型和传入的field参数,自动推断出精确的返回类型:

type SpecificTypeInformation = { foo: 'bar'; goo: 'baz' };
const x: 'bar' = getV<SpecificTypeInformation>({ field: 'foo' }); // 类型正确,无报错

为什么原类型断言写法有效

你用as MyLib.GetV<SpecificTypeInformation>断言时,实际上是将getV的类型从GetV<{[string]:any}>转换为GetV<SpecificTypeInformation>,此时内部函数的K约束变为keyof SpecificTypeInformation,传入'foo'自然会推断出正确的返回类型。但这种写法确实繁琐,上述两种方案可以替代它。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:44:52