es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Tipo mapeado que combina las variaciones del tipo dado.

Dado un tipo que contiene todas las posibilidades (por ejemplo, una unión no etiquetada):

type Input = {
  a: string,
  b: number,
  c: boolean,
};

Quiero mapearlo con este tipo de API:

type MapItSomehow<t> = ???;

type Output = MapItSomehow<input>;

Y, en última instancia, obtener esto:

type Output = {
  a: string,
  b: undefined,
  c: undefined,
} | {
  a: undefined,
  b: number,
  c: undefined,
} | {
  a: undefined,
  b: undefined,
  c: boolean,
};

La prueba de que esto funciona es si puedo hacer lo siguiente:

“`ts
let r: Result = ([] as Result[])[0];

if ('a' in r) {
r.a.trim() // no r.a!.trim()
}
else if // lo mismo para cada campo …
“`

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para lograr el mapeo deseado, podemos utilizar el operador keyof para generar un tipo unión con todas las claves en el tipo de entrada T. Luego, podemos usar tipos mapeados y tipos condicionales para crear un nuevo tipo que incluya todas las combinaciones posibles de campos en el tipo de entrada, con undefined como tipo para los campos excluidos. Aquí está el código:

    type Input = {
      a: string,
      b: number,
      c: boolean,
    };
    
    type MapItSomehow<t> = {[K in keyof T]: {[P in K]: T[K]} & {[P in Exclude<keyof t,="" k="">]?: undefined}}[keyof T];
    
    type Output = MapItSomehow<input>;
    

    Veamos esto más detalladamente. El tipo MapItSomehow mapea todas las claves K en el tipo de entrada T utilizando un tipo mapeado:

    {[K in keyof T]: {[P in K]: T[K]} & {[P in Exclude<keyof t,="" k="">]?: undefined}}
    

    Para cada clave K, este tipo crea un nuevo tipo objeto que incluye el campo K con su tipo original T[K], y todos los demás campos del tipo de entrada con el tipo undefined. El tipo de utilidad Exclude se utiliza para crear una unión con todas las otras claves del tipo de entrada, y el operador ?: se utiliza para hacer que esos campos sean opcionales con el tipo undefined.

    Finalmente, se utiliza el indexado [keyof T] para crear un tipo unión con todas las combinaciones posibles de campos en el tipo de entrada.

    Esto resulta en el tipo Output que estábamos tratando de lograr:

    type Output = {
      a: string,
      b: undefined,
      c: undefined,
    } | {
      a: undefined,
      b: number,
      c: undefined,
    } | {
      a: undefined,
      b: undefined,
      c: boolean,
    };
    

    Con esta definición de tipo, podemos utilizar el operador in para verificar si un campo está presente en un valor de tipo Output, y TypeScript correctamente estrechará el tipo del valor según la verificación.

Comments are closed.