Búsqueda de sitios web

Typescript. Tipado de funciones


Hola, estoy aprendiendo TypeScript y sigo estos ejercicios: Enlace

Tengo problemas para entender cómo debería proceder con este ejemplo.

hay un código así:

export function map(mapper, input) {
    if (arguments.length === 0) {
        return map;
    }
    if (arguments.length === 1) {
        return function subFunction(subInput) {
            if (arguments.length === 0) {
                return subFunction;
            }
            return subInput.map(mapper);
        };
    }
    return input.map(mapper);
}

y se supone que debo agregar tipos a esto. Logré crear algo así:

export function map<T>(mapper: Function, input : T[]| any) : T[] | Function {
    if (arguments.length === 0) {
        return map;
    }
    if (arguments.length === 1) {
        return function subFunction(subInput: T[]|any): T[] | Function {
            if (arguments.length === 0) {
                return subFunction;
            }
            return subInput.map(mapper);
        };
    }
    return input.map(mapper);
}

TypeScript ahora no devuelve errores de compilación, pero todavía fallo la prueba. No entiendo qué se espera de mí para que esto funcione.

Puedo revisar la respuesta sugerida, pero cuando la miro, esto es magia negra para mí.

Podría revisar test.ts para ver lo que se espera, pero una notación como const mapResult1=map()(String)()([1, 2, 3]); me parece muy extraña.

Respuesta #1

Bueno, es solo un caso de uso de la función map:

  • Al escribir map() el resultado es map en sí mismo
  • El siguiente paso es map(String) que devuelve subFunction
  • El siguiente paso es subFunction() que devuelve subFunction a sí mismo
  • El último paso es subFunction([1, 2, 3]) que devuelve el resultado de la expresión [1, 2, 3].map(String): ['1', '2', '3']

El tipo de este resultado es un string[] porque cada elemento del arreglo final es el resultado de que String se llame como una función, lo cual siempre es un string. Se supone que tus tipados deben resolver este tipo sin siquiera ejecutar el código.

Aquí hay una posible solución encontrada en el código fuente de los ejercicios que estás haciendo. De hecho, renovaron la implementación para hacerla "funcional" (devolver una nueva función para cada parámetro no resuelto)

function toFunctional<T extends Function>(func: T): Function {
    const fullArgCount = func.length;
    function createSubFunction(curriedArgs: unknown[]) {
        return function(this: unknown) {
            const newCurriedArguments = curriedArgs.concat(Array.from(arguments));
            if (newCurriedArguments.length > fullArgCount) {
                throw new Error('Too many arguments');
            }
            if (newCurriedArguments.length === fullArgCount) {
                return func.apply(this, newCurriedArguments);
            }
            return createSubFunction(newCurriedArguments);
        };
    }
    return createSubFunction([]);
}

interface MapperFunc<I, O> {
    (): MapperFunc<I, O>;
    (input: I[]): O[];
}

interface MapFunc {
    (): MapFunc;
    <I, O>(mapper: (item: I) => O): MapperFunc<I, O>;
    <I, O>(mapper: (item: I) => O, input: I[]): O[];
}

/**
 * 2 arguments passed: returns a new array
 * which is a result of input being mapped using
 * the specified mapper.
 *
 * 1 argument passed: returns a function which accepts
 * an input and returns a new array which is a result
 * of input being mapped using original mapper.
 *
 * 0 arguments passed: returns itself.
 */
export const map = toFunctional(<I, O>(fn: (arg: I) => O, input: I[]) => input.map(fn)) as MapFunc;

Respuesta #2

Aquí hay una solución simple:

interface SubFunction<I, O> {
  (): SubFunction<I, O>;
  (input: I[]): O[];
}

function map<I, O>(): typeof map;
function map<I, O>(mapper: (i: I) => O): SubFunction<I, O>;
function map<I, O>(mapper: (i: I) => O, input: I[]): O[];

function map<I, O>(mapper?: (i: I) => O, input?: I[]) {
  if (mapper && input) {
    return input.map(mapper);
  }
  if (mapper) {
    const subFunction = (input?: I[]) => input ? input.map(mapper) : subFunction;
    return subFunction;
  }
  return map;
}

const mapResult1 = map()(String)()([1, 2, 3]);
  • Utiliza un tipo de ayuda para la SubFunción.
  • Utiliza TypeScript moderno e idiomático (sin function aparte del nivel superior, sin arguments)
  • Utiliza sobrecarga de funciones para tener diferentes tipos de retorno.

Patio de recreo

Artículos relacionados