Cómo obtener el tipo de unión anidada en TypeScript
Estoy usando graphql codegen que generó este tipo para mí:
export type GetOffersForMembershipQuery = {
__typename?: "Query";
offers:
| { __typename?: "BaseError" }
| {
__typename?: "QueryOffersSuccess";
data: Array<{
__typename?: "Offer";
title: string;
details: string;
identifier: string;
merchant?: {
__typename?: "Merchant";
logoImageUrl?: string | null;
} | null;
}>;
}
| { __typename?: "ValidationError" };
};
Quiero extraer el tipo de data aquí. ¿Cómo puedo hacer esto?
Intenté hacer simplemente:
GetOffersForMembershipQuery["offers"]["data"];
Pero, por supuesto, el problema es que ["data"] no existe si el __typename no es "QueryOffersSuccess".
Respuesta #1
Puedes usar Extract para extraer solo los miembros de una unión que extiende un tipo.
type MyData =
Extract<GetOffersForMembershipQuery['offers'], { data: unknown }>['data']
El tipo de utilidad Extract está documentado como:
type Extract<T, U> = T extends U ? T : never
// Extract from T those types that are assignable to U
Entonces, en este caso, extrae todos los miembros que se puedan asignar a { data: unknown }, que en este caso es el único miembro con la propiedad data, lo que hace que sea seguro acceder a esa propiedad.
Ver el patio de recreo
Respuesta #2
ACTUALIZACIÓN
Empecé a trastear, y me pregunto si esto hace lo que necesitas?
type test = GetOffersForMembershipQuery['offers'] extends { __typename: infer U } ? U : never
type t2 = test['data']
Respuesta Original
Creo que esta respuesta tiene todo lo que necesitas. Empecé a jugar con NonNullable<T> para que funcionara, pero eso es para obtener tipos opcionales, y aunque funciona con anidamiento cuando se encadena, esto todavía muestra un error:
type Response = NonNullable<NonNullable<GetOffersForMembershipQuery["offers"]>["data"]>;
La razón por la que eso todavía no es suficiente, es que tu tipo también es un Union. Sin embargo, busqué un poco por ti, y creo que el enlace que compartí contiene todas las partes necesarias.
