¿Hay una manera de resolver una declaración de tipo que acepte una unión de una cadena y una función?

Tengo esta definición de tipo, incompleta en este momento:

export type Type1 = string;

export type Type2 = string | { [index: string]: any } | Array;

export type Type3 = { [index: string]: any } | Array;

export type Type4 = (arg1?: Type2 | Type3, arg2?: Type3) => string | undefined;

export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): Type4;

Normalmente la biblioteca se utiliza en escenarios como el siguiente ejemplo, tipos de declaración funciona correctamente en este ejemplo, dentro de la aplicación React:

const myCustomLibrary = myLibrary('string')
...

Donde value puede ser cualquier cosa como un booleano, String, objeto ..

Pero dije una definición incompleta porque no está cubriendo el siguiente escenario, todavía dentro de una aplicación React:


Básicamente myLibrary puede devolver una función o también una cadena, dependiendo de los valores recibidos como entrada según una lógica interna específica. Así que el tipo Type4 también podría ser una String, no sólo un método que devuelve una String. Declaración de tipo actual ofrece sólo el tipo Type4 como salida, pierde una String simple. De hecho, al devolver una String, aquí está el error:

TS2322: Type 'Type4' is not assignable to type 'string'.

Así que pensé en añadir una cadena al valor de retorno myLibrary

export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): Type4 | string;

pero esto arruina otros escenarios actualmente trabajando (el que recibe el real Type4 y da este error

Cannot invoke an expression whose type lacks a call signature. Type 'string | Type4' has no compatible call signatures.ts(2349)

Siéntete en un agujero, ¿qué estoy haciendo mal? Podría resolver todo definiendo Type4 como any, pero eso no es lo que quiero lograr.

Pregunta hecha hace 3 años, 4 meses, 25 días - Por syntaxsensei


3 Respuestas:

  • La solución es efectivamente el uso de Sobrecargas concepto, gracias @AlekseyL. por la punta en los comentarios, para una referencia más clara Agrego aquí el correcto código.

    export default function myLibrary(arg1?: Type1, arg2?: Type1): Type4;
    
    export default function myLibrary(arg1: Type1, arg2: Type3 | undefined): string;
    
    export default function myLibrary(arg1: Type1, arg2: Type2, arg3: Type3): string;
    

    Respondida el Dec 20, 2020 a las 10:59 - por techtactician

    Votos positivos: 0 | Votos negativos: 0

  • Para resolver este problema y permitir que la declaración de tipo acepte una unión de una cadena y una función, puedes utilizar una técnica conocida como "diferenciación de tipos" en TypeScript. De esta manera, se puede definir un tipo genérico que representa tanto una función como una cadena.

    Aquí te dejo un ejemplo de cómo podrías modificar tus definiciones de tipo para lograrlo:

    typescript
    type FunctionType = (...args: any[]) => string;
    
    export type Type4 = FunctionType | string;
    
    export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): Type4;
    

    Con esta modificación, la declaración de tipo Type4 ahora acepta tanto una función que devuelve una cadena como una cadena simple. Esto permitirá el comportamiento que deseas, donde myLibrary puede devolver tanto una función como una cadena dependiendo de los valores recibidos.

    Espero que esta solución te sea útil. Si tienes alguna otra pregunta o duda, no dudes en decírmelo.

    Respondida el Dec 21, 2020 a las 11:02 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Para resolver el problema de declarar un tipo que acepte una unión de una cadena y una función, puedes utilizar declaraciones de tipo genérico. Los tipos genéricos te permiten definir un tipo que puede aceptar diferentes tipos de datos como parámetros.

    En tu caso, puedes definir un tipo genérico llamado ReturnType que acepte un parámetro de tipo T. Este parámetro de tipo representará el tipo de valor de retorno de la función.

    
    export type ReturnType = T | string;
    

    Ahora puedes utilizar este tipo genérico para definir el tipo de retorno de tu función myLibrary:

    
    export default function myLibrary(arg1?: Type1, arg2?: Type2, arg3?: Type3): ReturnType;
    

    Esto significa que la función myLibrary puede devolver un valor de tipo Type4 o una cadena.

    Al utilizar el tipo genérico ReturnType, puedes evitar el error TS2322 al devolver una cadena, ya que el tipo ReturnType<Type4> incluye tanto Type4 como string.

    Además, esto no romperá los escenarios existentes en los que la función devuelve un valor de tipo Type4, ya que el tipo Type4 sigue siendo compatible con el tipo ReturnType<Type4>.

    Respondida el Dec 21, 2020 a las 11:13 - por Gemini

    Votos positivos: 0 | Votos negativos: 0