typescript - 给定一个对象数组,是否可以泛化一个函数以给出给定键值的字符串文字联合?
问题描述
鉴于此参考代码:
const stuff = [
{ name: "Rock", children: [{ name: "Pebbles", children: undefined }] },
{ name: "Tree" },
{ name: "Sun" },
] as const
// Evaluates to `type Names = "Rock" | "Pebbles" | "Tree" | "Sun"`
type Names = typeof stuff[number]["name"] | typeof stuff[0]["children"][0]["name"]
是否可以概括 Names 类型,以便我可以让它给我所有name
属性值的字符串文字联合,无论它在对象中的什么位置?
解决方案
type Names<T> = T extends readonly unknown[] ?
T[number] extends infer O
? O extends object
? {
[K in keyof O]: 'name' extends K
? O[K]
: Names<O[K]>
}[keyof O]
: never
: never
: never
首先我们检查T
类型是否为数组类型:
T extends readonly unknown[] ?
接下来我们介绍类型变量O
:
T[number] extends infer O
这完全是修饰步骤,因为我不想在现在出现在类型中的T[number]
任何地方重复。O
由于条件类型的分布性质,O
现在每次迭代都有每个
迭代数组元素的类型。
检查是否O
实际上是一个对象:
? O extends object
最后是主要部分。映射[keyof O]
类型通过查找立即减少为联合:
{
[K in keyof O]: 'name' extends K ? O['name'] : Names<O[K]>
}[keyof O]
这个本质上迭代了O
对象的所有键,如果键值是name
get 的类型,O[K]
否则尝试name
从O[K]
.
[keyof O]
如果我们删除查找,它可能有助于掌握内部发生的事情:
type Names<T> = T extends readonly unknown[] ?
T[number] extends infer O
? O extends object
? {
[K in keyof O]: 'name' extends K ? O[K] : Names<O[K]>
}
: never
: never
: never
const stuff = [
{ name: "Rock", children: [{ name: "Pebbles", children: undefined }] },
{ name: "Tree" },
{ name: "Sun" },
] as const
/*
type N = {
readonly name: "Rock";
readonly children: {
readonly name: "Pebbles";
readonly children: never;
};
} | {
readonly name: "Tree";
} | {
readonly name: "Sun";
}
*/
type N = Names<typeof stuff>
当我们[keyof O]
查找每个映射对象时,我们得到:
type N = {
readonly name: "Rock";
readonly children: {
readonly name: "Pebbles";
readonly children: never;
}['name' | 'children'];
}['name' | 'children'] | {
readonly name: "Tree";
}['name'] | {
readonly name: "Sun";
}['name']
//
type N = "Rock" | "Pebbles" | "Tree" | "Sun" // result type
推荐阅读
- python - 将 json 对象转换为 pyspark 数据框
- amazon-web-services - 使用 Elemental MediaPackage 在 aws 上继续观看存储视频的功能
- ruby - 如何在 ruby 中抓取输入框的值?
- android - KOTLIN 中 mvvm 结构中的折线图
- powershell - 使用数组作为哈希表中的键
- linux - 使用 Freetype 和 Mingw 的未定义引用
- javascript - 我得到了 = removeChild 不是函数
- scala - 如何将 Spark RDD 转换为 Spark DataFrame
- java - 使用 java.util.Random 制作自定义类,不断返回 NullPointerException
- javascript - 为什么提取的 html 文件的脚本不执行?