3 votes

Dactylographié. Dactylographie des fonctions

Bonjour, je suis en train d'apprendre le typage et je suis ces exercices : Lien

J'ai du mal à comprendre comment je dois procéder avec cet exemple.

il y a un code comme celui-ci :

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);
}

et je suis censé y ajouter des types. J'ai réussi à créer quelque chose comme ceci :

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);
}

Les typescript ne renvoient plus d'erreurs de compilation maintenant mais j'échoue toujours le test. Je ne comprends pas ce que l'on attend de moi pour que cela fonctionne.

Je peux vérifier la réponse suggérée mais quand je regarde, c'est de la magie noire pour moi.

Je pourrais vérifier test.ts pour ce qui est attendu, mais une notation comme const mapResult1 = map()(String)()([1, 2, 3]); est très étrange pour moi.

1voto

Twisting nether Points 4723

Eh bien, c'est juste un cas d'utilisation de la map fonction :

  • Lors de la rédaction map() le résultat est map lui-même
  • L'étape suivante est map(String) qui renvoie subFunction
  • L'étape suivante est subFunction() qui renvoie subFunction lui-même
  • La dernière étape est subFunction([1, 2, 3]) qui renvoie le résultat de l'expression [1, 2, 3].map(String) : ['1', '2', '3']

Le type de ce résultat est un string[] parce que chaque élément du tableau final est le résultat de String être appelé comme une fonction est toujours un string . Vos typages sont censés résoudre ce type sans même exécuter le code.

Voici une solution possible trouvée dans le code source des exercices que vous faites. Ils ont en fait remanié l'implémentation pour la rendre "fonctionnelle" (retourner une nouvelle fonction pour chaque paramètre non résolu).

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;

1voto

Clashsoft Points 1633

Voici une solution 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]);
  • Il utilise un type d'aide pour la sous-fonction.
  • Il utilise l'idiomatique TypeScript moderne (pas de function en dehors du niveau supérieur, aucune arguments )
  • Il utilise la surcharge de fonction pour avoir différents types de retour.

Terrain de jeux

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X