首页 > 解决方案 > 键入对象中的键,其中该键的值满足约束

问题描述

我有这样的事情:

显然这是一个过于简单的例子,所以我为什么要专门做这些类型的问题是无关紧要的。

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" }

这可能吗?

标签: typescripttype-constraints

解决方案


我相信您正在寻找类似的东西:

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 中发布的相对较新的密钥重新映射功能。

游乐场链接


推荐阅读