区分联合类型的TypeScript实用程序类型

时间:2020-02-07 10:39:53

标签: typescript

给出这样的可区分联合类型:

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)

2 个答案:

答案 0 :(得分:2)

您可以使用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

答案 1 :(得分:1)

最冗长的解决方案是:

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

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

我们还可以使用现有的实用程序类型提取,它将提取条件类型以供使用:

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