Dado un tipo de unión discriminada como este:
type HomeRoute = { name: 'Home' };
type PageRoute = { name: 'Page'; id: number };
type SearchRoute = { name: 'Search'; text: string; limit?: number };
type Route = HomeRoute | PageRoute | SearchRoute;
Me gustaría un tipo de utilidad que tome el tipo de unión y sea el discriminante (aquí el tipo del nombre del miembro: "Home" | "Page" | "Search"
) y devuelve el caso coincidente:
type Discriminate<TUnion, TDiscriminant> = ???
type TestHome = Discriminate<Route, 'Home'>; // Expecting "HomeRoute" (structure)
type TestPage = Discriminate<Route, 'Page'>; // Expecting "PageRoute" (structure)
2 respuestas
La solución más detallada sería:
type Discriminate<TUnion, TDiscriminant> =
TUnion extends {name: TDiscriminant} ? TUnion : never
type HomeMember = Discriminate<Route, 'Home'>;
type PageMember = Discriminate<Route, 'Page'>;
Podemos usar también el tipo de utilidad existente Extract, que hará un tipo condicional para su uso:
type Discriminate<TUnion, TDiscriminant> = Extract<TUnion, {name: TDiscriminant}>
Puede usar el tipo condicional predefinido 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' }>;
También puede crear una versión genérica de Discriminate
pero no está seguro de si vale la pena, ya que también necesitaría el campo:
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)
Preguntas relacionadas
Preguntas vinculadas
Nuevas preguntas
typescript
TypeScript es un superconjunto escrito de JavaScript que se compila en JavaScript simple. Agrega tipos, clases, interfaces y módulos opcionales a JavaScript. Esta etiqueta es para preguntas específicas de TypeScript. No se utiliza para preguntas generales de JavaScript.