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

关于TypeScript结构类型系统的疑问及代码示例解析

关于TypeScript结构类型系统的疑问及代码示例解析

嘿,我来帮你拆解这个TypeScript的小困惑!先看你给出的这段代码示例:

type Foo1<K extends string, V> = { [key in K]: V }
type Foo2<K extends string, V> = { [key in K]: V }

function values1<T>(foo: Foo1<string, T>) {
  return Object.values(foo)
}
function values2<T>(foo: Foo2<string, T>) {
  return Object.values(foo)
}

function test<K extends string>(foo: Foo1<K, string>) {
    const v1 = values1(foo) // string[]
    const v2 = values2(foo) // unknown[]
}

是不是很奇怪?明明Foo1和Foo2的定义完全一模一样,为什么把同一个foo传给values1和values2,返回值类型会差这么多?我来给你捋清楚:

  • 首先,TypeScript是结构类型系统,理论上结构完全相同的类型应该是兼容的,但这里的关键在于泛型类型的身份匹配。
  • 当你把foo(类型是Foo1<K, string>)传给values1时,values1的参数是Foo1<string, T>——这俩都是Foo1这个泛型的不同实例。TypeScript能顺着同一个泛型的结构关联,推断出T应该是string(因为foo里所有属性的值都是string类型),所以values1(foo)的返回值就是string[]。
  • 而传给values2的时候,情况就不一样了:values2的参数是Foo2<string, T>,虽然Foo2和Foo1结构完全相同,但它们是TypeScript里两个独立定义的泛型类型。这时候TypeScript没办法直接把Foo1<K, string>和Foo2<string, T>的泛型参数做精准匹配,没办法确定T的具体类型,只能 fallback 到最宽泛的unknown,所以values2(foo)的返回值就成了unknown[]。

简单说就是:同名泛型的不同实例之间,TypeScript的类型推断会更“聪明”;而两个结构相同但名字不同的泛型,在跨类型推断时会更保守,容易出现类型丢失的情况。

备注:内容来源于stack exchange,提问作者riv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:43:11