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.

¿Cómo hacer que los tipos fantasma funcionen con métodos en TypeScript?

Considere el siguiente programa que utiliza tipos fantasma:

const strlen = (str: string) => str.length;

type Const<a, b=""> = { type: 'Const', value: A };

const Const = <a, b="never">(value: A): Const<a, b=""> => ({ type: 'Const', value });

const map = <a, b,="" c="">(_f: (value: B) => C, { value }: Const<a, b="">): Const<a, c=""> => Const(value);

const contramap = <a, b,="" c="">(_f: (value: C) => B, { value }: Const<a, b="">): Const<a, c=""> => Const(value);

const constant = Const(true);

map(strlen, constant); // funciona

contramap(strlen, constant); // funciona

El programa anterior se verifica correctamente porque se infieren los tipos correctos. El valor constant tiene el tipo inferido Const<boolean, never="">. La función map se llama con los tipos A = boolean, B = string y C = number. La función contramap se llama con los tipos A = boolean, B = number y C = string.

Sin embargo, sería bueno escribir las expresiones anteriores utilizando métodos en lugar de funciones. Por lo tanto, intenté lo siguiente:

const strlen = (str: string) => str.length;

interface Const<a, b=""> {
    map: <c>(f: (value: B) => C) => Const<a, c="">;
    contramap: <c>(f: (value: C) => B) => Const<a, c="">;
}

const Const = <a, b="never">(value: A): Const<a, b=""> => ({
    map: () => Const(value),
    contramap: () => Const(value)
});

const constant = Const(true);

constant.map(strlen); // funciona

constant.contramap(strlen); // error

Como se puede ver, el método map funciona pero el método contramap no. Esto se debe a que el tipo de constant es Const<boolean, never=""> y no se refina con la llamada al método, es decir, para map el tipo no se refina a Const<boolean, string=""> y para contramap el tipo no se refina a Const<boolean, number="">.

Debido a esto, tanto map como contramap funcionan pero no ambos. Si el tipo del objeto es Const<boolean, never="">, entonces contramap no funciona. Si el tipo del objeto es Const<boolean, unknown="">, entonces map no funciona.

¿Cómo puedo hacer que tanto map como contramap funcionen utilizando métodos en lugar de funciones?</boolean,></boolean,></boolean,></boolean,></boolean,></a,></a,></a,></a,></a,></boolean,></a,></a,></a,></a,></a,></a,></a,></a,></a,>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para hacer que tanto map como contramap funcionen utilizando métodos en lugar de funciones, podemos utilizar el encadenamiento de métodos y devolver this con el tipo refinado después de cada llamada al método. Aquí está una versión actualizada del código:

    const strlen = (str: string) => str.length;
    
    interface Const<a, b=""> {
        map<c>(f: (value: B) => C): Const<a, c="">;
        contramap<c>(f: (value: C) => B): Const<a, c="">;
    }
    
    const Const = <a, b="never">(value: A): Const<a, b=""> => ({
        map: <c>(f: (value: B) => C) => Const(f(value)),
        contramap: <c>(f: (value: C) => B) => Const(f(value)),
    });
    
    const constant = Const(true);
    
    constant.map(strlen).contramap((n: number) => n.toString()); // funciona
    

    En esta versión, llamar a map o contramap devuelve Const<a, c=""> en lugar de solo Const<a, b="">. Luego podemos encadenar varias llamadas de método juntas para refinar aún más el tipo.

    Tenga en cuenta que también necesitamos especificar el tipo del argumento en la llamada de contramap para ayudar a TypeScript a inferir el tipo correcto.</a,></a,></a,></a,></a,></a,></a,>

Comments are closed.