【问题标题】:TypeScript utility type over a discriminated union type区分联合类型上的 TypeScript 实用程序类型
【发布时间】:2020-05-23 11:47:30
【问题描述】:

给定一个像这样的有区别的联合类型:

type HomeRoute   = { name: 'Home' };
type PageRoute   = { name: 'Page'; id: number };
type SearchRoute = { name: 'Search'; text: string; limit?: number };

type Route = HomeRoute | PageRoute | SearchRoute;

我想要一个实用程序类型,它采用联合类型及其判别式(这里是名称成员的类型:"Home" | "Page" | "Search")并返回匹配的大小写:

type Discriminate<TUnion, TDiscriminant> = ???

type TestHome = Discriminate<Route, 'Home'>; // Expecting "HomeRoute" (structure)
type TestPage = Discriminate<Route, 'Page'>; // Expecting "PageRoute" (structure)

【问题讨论】:

  • 有趣,但什么是动力。判别式应被视为实现细节
  • @MaciejSikora:我需要一些提示来给这个answerExtract 实用程序类型就足够了,但是您和@Titian 通用答案都非常有趣。谢谢

标签: typescript


【解决方案1】:

你可以使用Extract预定义的条件类型:

type HomeRoute   = { name: 'Home' };
type PageRoute   = { name: 'Page'; id: number };
type SearchRoute = { name: 'Search'; text: string; limit?: number };

type Route = HomeRoute | PageRoute | SearchRoute;

type TestHome = Extract<Route, { name: 'Home' }>; 
type TestPage = Extract<Route, { name: 'Page' }>; 

您还可以创建Discriminate 的通用版本,但不确定是否值得,因为您还需要该字段:


type Discriminate<TUnion, TField extends PropertyKey, TDiscriminant> = Extract<TUnion, Record<TField, TDiscriminant>>

type TestHome = Discriminate<Route, 'name', 'Home'>; // Expecting "HomeRoute" (structure)
type TestPage = Discriminate<Route, 'name', 'Page'>; // Expecting "PageRoute" (structure)

Playground Link

【讨论】:

  • 针对他的情况进行简化,需要type Discriminate&lt;TUnion, TDiscriminant&gt; = Extract&lt;TUnion, Record&lt;'name', TDiscriminant&gt;&gt;
【解决方案2】:

最详细的解决方案是:

type Discriminate<TUnion, TDiscriminant> = 
  TUnion extends {name: TDiscriminant} ? TUnion : never

type HomeMember = Discriminate<Route, 'Home'>;
type PageMember = Discriminate<Route, 'Page'>; 

我们也可以使用现有的实用程序类型 Extract 来做条件类型供使用:

type Discriminate<TUnion, TDiscriminant> = Extract<TUnion, {name: TDiscriminant}>

【讨论】:

    猜你喜欢
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多