typescript - 键入对象中的键,其中该键的值满足约束
问题描述
我有这样的事情:
显然这是一个过于简单的例子,所以我为什么要专门做这些类型的问题是无关紧要的。
type Bird = { kind: "bird" }
type Fish = { kind: "fish" }
const zoo = {
flamingo: { kind: "bird" },
hawk: { kind: "bird" },
chicken: { kind: "bird" },
guppy: { kind: "fish" },
blowfish: { kind: "fish" }
}
我想获得可能是这样的字符串数组类型:
type FishInZoo = "guppy" | "blowfish"
type BirdInZoo = "flamingo" | "hawk" | "chicken"
所以我在想类似下面的东西,但我不知道语法是什么:
type FishInZoo = keyof typeof zoo where { kind: "fish" }
这可能吗?
解决方案
我相信您正在寻找类似的东西:
type GetKeysOfType<
Type extends Record<string, any>,
Obj extends Record<string, any>
> = keyof {
[Key in keyof Obj as Obj[Key] extends Type ? Key : never]: Obj[Key];
}
请注意,这将需要as const
对对象进行断言,请参阅文档。这允许您在对象中使用字符串文字并输入 ie
type Bird = { kind: "bird" }
type Fish = { kind: "fish" }
// as opposed to
type Kind = { kind: string };
使用它需要您指定:
const zoo = {
flamingo: { kind: "bird" },
hawk: { kind: "bird" },
chicken: { kind: "bird" },
guppy: { kind: "fish" },
blowfish: { kind: "fish" }
} as const // this as const.
然后你使用这样的类型:
type BirdsInZoo = GetKeysOfType<Bird, typeof zoo>
type FishesInZoo = GetKeysOfType<Fish, typeof zoo>
您还可以强制所有使用的对象GetKeysOfType
必须是Readonly
必须使用as const
的,以防止人们忘记和接收不正确的值。但这取决于您的用例。
它使用4.1 中发布的相对较新的密钥重新映射功能。
推荐阅读
- visual-studio-code - 如何使用 emmet 更改数基数和方向
- php - Laravel 中带有 ID 和 Slug 的 URL 的路径函数
- python - 在python中改变海龟的颜色
- email - 域名转移后邮件崩溃
- python - 如何将 torchvision.datasets.ImageFolder 加载到 google colab ram
- ruby-on-rails - 如何在 Rails ActiveRecord 中返回生成的列?
- python - Python + 破折号 + 引导
- python - 抓取编码错误的 html
- vue.js - 在 HTML 中循环对象时,我需要帮助在 Vuejs2 中调用 watcher
- r - 将 csv 导入 R,提取多边形并使用 googlePolylines 包对其进行解码