【问题标题】:How to select a key from a discriminated union type?如何从可区分的联合类型中选择一个键?
【发布时间】:2023-01-13 18:48:38
【问题描述】:
我有一个受歧视的工会
type MyDUnion = { type: "anon"; name: string } | { type: "google"; idToken: string };
我想直接从 MyDUnion 类型的判别联合访问名称键。像这样的东西
type Name = MyDUnion['name']
但是打字稿不允许这样做
Property 'name' doesn't exist on type '{ type: "anon"; name: string } | { type: "google"; idToken: string }'
我怎样才能访问它?
需要明确的是,这是不是一个有效的解决方案:
type MyName = string;
type MyDUnion = { type: "anon"; name: MyName } | { type: "google"; idToken: string };
type Name = MyName; // this line would be in a different file
这是无效的,因为那时我将不得不导出 MyName 和 MyDUnion 类型以在其他地方使用。
有任何想法吗?
【问题讨论】:
标签:
javascript
typescript
discriminated-union
【解决方案1】:
为了获得所需的密钥,您必须以某种方式告诉 Typescript 编译器
嘿编译器,我想知道这个对象,在一个非常具体的情况下
在本例中,您想了解有关对象的信息,即type ==='anon'。所以,以你的例子,
type MyDUnion = { type: "anon"; name: string } | { type: "google"; idToken: string };
type SpclCase = MyDUnion & {type: "anon"}
通过这样做,您将获得有关这两种情况何时重叠的信息。现在您可以直接索引 name 键。
type Name = SpclCase['name']
如果你想让它更健壮,我们可以确保我们使用的缩小类型(在本例中为{type: 'anon'})满足所需的形状。这是一个临时的解决方案。
type DiscriminatorObj = { type: 'anon' }
type RequiredCase = DiscriminatorObj extends Pick<MyDUnion, "type"> ? DiscriminatorObj: never;
type SpclCase = (RequestBody & RequiredCase);
type Name = SpclCase['name']
我知道它的边缘有点粗糙,但你总是可以将它提取到通用函数中并随意使用它们。我只是向你展示了基本逻辑。您可以使用它使它更美观。