typescript 泛型与内置 Record 使用问题 ?

作者站长头像
站长
· 阅读数 7

默认使用 Record 的例子内置 Record 会遍历 CatName 联合类型,每个字面量类型的值是 CatInfo 类型

interface CatInfo {
  age: number;
  breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
  miffy: { age: 10, breed: "Persian" },
  boris: { age: 8, breed: "Maine Coon" },
  mordred: { age: 16, breed: "Brittish Shorthair" },
};

使用泛型的另一个例子在调用say函数时并没有传递泛型,ts会自动将泛型T设置为 string

function say<T>(arg: T) {
  console.log(arg)
}
say('abc')

请问在下面这个例子中为什么会自动将对象字面量的key和value拆开传递到 Record 中?我个人理解是使用函数的时候没有主动传递泛型,ts内部会使用函数调用时参数的值做为类型,但 Record 需要 2 个泛型,对象字面量只有一个类型,这块的运行机制是?

function fn<K extends keyof any, V>(o: Record<K, V>) {
  console.log(o);
}

fn({ name: "zhangsan", age: 666, address: { num: 1 } })

/*
function fn<"name" | "age" | "address", string | number | {
    num: number;
}>(o: Record<"name" | "age" | "address", string | number | {
    num: number;
}>): void
*/
回复
1个回答
avatar
test
2024-07-12

{ name: "zhangsan", age: 666, address: { num: 1 } } 的键和值类型集分别是:

  • 键类型:"name" | "age" | "address"
  • 值类型:string | number | { num: string }

所以它作为一个对象的类型,去匹配 Record<K, V> 的话,就是

  • type K = "name" | "age" | "address"
  • type V = string | number | { num: string }

这是 TypeScript 推导出来的:通过参数的类型,按其兼容性和函数声明的参数类型进行推导找出来的。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容