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.

Typescript infiere el objeto como “never” cuando verifica si existe una propiedad condicional.

Tengo un tipo llamado T que acepta un tipo genérico Str que extiende string. Si Str extiende "hello", entonces el tipo T debería tener una propiedad adicional llamada B. Algo como esto:

export type T<str extends="" string=""> = {
  A: number;
} & (Str extends "hello" ? { B?: number } : {});

Basado en ese tipo, se comporta de la siguiente manera:

type T1 = T<"hello">; // type T1 = { A: number; B?: number | undefined; }
type T2 = T<"world">; // type T2  = { A: number; }

Ahora, quiero crear una función que acepte este tipo como argumento y agregue una lógica adicional basada en la existencia de la propiedad B:

function t<type extends="" string="">(arg: T<type>) {
  if ("B" in arg) {
    // ...
  }
}

Sin embargo, obtengo un error que indica que arg dentro de la declaración if se considera como never.

Ver en playground

Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema con la implementación actual de la función t es que TypeScript no puede inferir que la presencia de la propiedad B en arg está mapeada al parámetro de tipo Str que extiende “hello”. Por lo tanto, arg se considera como no teniendo ninguna propiedad y se infiere como never.

    Para resolver este problema, podemos utilizar una función de tipo que verifique la presencia de la propiedad B y devuelva un booleano en función de esa verificación. Esta función de tipo puede ser utilizada dentro de la declaración if para estrechar el tipo de arg e incluir la propiedad adicional B.

    Aquí hay una implementación actualizada de la función t con la función de tipo de verificación:

    function hasB<type extends="" string="">(arg: T<type>): arg es T<type> & { B: number } {
      return "B" in arg;
    }
    
    function t<type extends="" string="">(arg: T<type>) {
      if (hasB(arg)) {
        // arg ahora se ha estrechado a T<type> & { B: number }
        arg.B = arg.B ?? 0;
        // hacer algo con arg.B
      }
    }
    

    La función hasB verifica si arg tiene la propiedad B y devuelve un booleano en función de eso. La sintaxis arg es T<type> & { B: number } es un predicado de tipo que indica a TypeScript que si la condición dentro de la declaración if es verdadera, entonces el tipo de arg debería estrecharse e incluir la propiedad adicional B.

    Usando la función de tipo de verificación, ahora podemos acceder de forma segura a la propiedad B dentro de la declaración if sin errores. Además, también podemos agregar un valor predeterminado a arg.B utilizando el operador de fusión nula ??.

Comments are closed.