Внедрить контекст в несколько функций карри с одним и тем же первым параметром карри - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть несколько карри-функций в одном месте, которые все принимают context параметр и возвращают функцию, которая принимает один или несколько аргументов и возвращает разные типы.

Я подумал, что было бы интересно ввести context для всех этих функций одновременно и впоследствии использовать функции withContext. Но я не хочу потерять типизацию функций в процессе.

Это реальный код, который я пробовал:

import { map, filter } from '../controllers';

function makeProcessResult({
    database,
    logging,
}: ProcessResultConfig) {
    return async function processResult(results: Obj[], context: ExecutionOptions) {
        const [
            processResultLogger,
            mapWithContext,
            filterWithContext,
            saveResultsWithContext,
        ] = [
            logging, // type is Loggers['processResult'] (see types)
            map, // type is (context: ExecutionOptions) => (results: Obj[]) => Promise<Obj[]>
            filter, // type is the same as map
            database.saveProcessedResults // type is the same as map
        ].map(injectContext(context)); // I get the error here (pasted at the end)

        // const processResultLogger = logging(context);
        const mappedResults: Obj[] = await mapWithContext(results);
        const filteredResults: Obj[] = await filterWithContext(mappedResults);
        const savedResulst = await saveResultsWithContext(results);
        processResultLogger.finalResultsSaved();
        return filteredResults;
    }



    function injectContext<A>(context: ExecutionOptions) {
        return (fn: (context: ExecutionOptions) => A) => fn(context);
    }
}

Далее приведены функции и типы, которые используются в основной части:

interface Obj {
    [key: string]: any
}

type LoggerFn = (...args: any) => Promise<void>

interface Loggers {
    map: (ctx: ExecutionOptions) => {
        transformationsLoaded: LoggerFn
        mappedSuccessfully: LoggerFn
        mapperFailed: LoggerFn
    }
    filter: (ctx: ExecutionOptions) => {
        filteredByBlackList: LoggerFn
        filteredSuccessfully: LoggerFn
        filterFailed: LoggerFn
    }
    processResult: (ctx: ExecutionOptions) => {
        finalResultsSaved: LoggerFn
    }
}

interface Database {
}

interface ProcessResultDatabase extends Database {
    saveProcessedResults: (context: ExecutionOptions) => (results: Obj[]) => Promise<Obj[]>
}

interface ProcessResultConfig {
    database: ProcessResultDatabase
    logging: Loggers['processResult']
}

Функции map, filter и database.saveProcessedResults имеют одинаковую подпись: (context: ExecutionOptions) => (results: Obj[]) => Promise<Obj[]>

Ошибка:

Аргумент типа '(fn: (context: ExecutionOptions) => {finalResultsSaved: LoggerFn;} & ((results: Obj []) => Promise)) => {finalResultsSaved: LoggerFn; } & ((results: Obj []) => Promise <...>) 'нельзя назначить параметру типа' (значение: ((ctx: ExecutionOptions) => {finalResultsSaved: LoggerFn;}) | ((context : ExecutionOptions) => (результаты: Obj []) => Обещание), индекс: число, массив: (((ctx: ExecutionOptions) => {...;}) | ((контекст: ExecutionOptions) => (результаты : Obj []) => Обещание <...>)) []) => {...; } & ((results: Obj []) => Promise <... '. <br>Типы параметров' fn 'и' value 'несовместимы. Type' ((ctx: ExecutionOptions) => {finalResultsSaved: LoggerFn; }) | ((context: ExecutionOptions) => (results: Obj []) => Promise) «нельзя назначить типу» (context: ExecutionOptions) => {finalResultsSaved: LoggerFn;} & ((results: Obj [] ) => Обещание) '. Тип' (ctx: ExecutionOptions) => {finalResultsSaved: LoggerFn;} 'нельзя назначить типу (context: ExecutionOptions) => {finalResultsSaved: LoggerFn;} & ((результаты: Obj [] ) => Обещание) '. Тип' {finalResultsSaved: LoggerFn;} 'нельзя назначить типу {{finalResultsSaved: LoggerFn;} & ((результаты: Obj []) => Обещание)'. Тип '{finalResultsSaved: LoggerFn; } 'нельзя присвоить типу' (результаты: Obj []) => Promise '. Тип' {finalResultsSaved: LoggerFn;} 'не обеспечивает совпадения для подписи' (результаты: Obj []): Promise'.ts (2345 )

Мне было интересно, есть ли правильный способ генерировать injectContext, поэтому он будет работать с разными т входных и возвращаемых типов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...