生成一个需要原始函数的一个参数的函数

时间:2020-05-30 13:41:13

标签: typescript

我想知道我是否尝试设计一种替代现有功能签名的功能是否有效。我正在使用打字稿,并希望保持打字安全。

wrap1接受一元函数并返回具有相同签名的函数。它确实为原始功能提供了一些副作用。例如,副作用是对数。

type Func<T, U> = (input: T) => U;
type Log = () => void;
const wrap1 = <T, U>(log: Log, f: Func<T, U>) => 
    (i: T) => {
        log();
        return f(i);
    };

以这种方式生成许多功能,而这些功能被业务代码所使用。

后来,我发现控制日志格式或严重性的要求。

type LogOptions1 = {};
type LogOptions2 = {};
const formatLog1 = (options: LogOptions1, log: Log) => log; // Please ignore the function implementation.
const formatLog2 = (options: LogOptions2, log: Log) => log;

所以我开发了一个实用程序函数,该函数将一个额外的log选项参数附加到原始函数中。

type FormatLog<OptionType, Log> = (options: OptionType, log: Log) => Log;
const addOption = <LogOptionType>(
    logFormatter: FormatLog<LogOptionType, Log>
) => <T, U>(
    wrap: (log: Log, f: Func<T, U>) => Func<T, U>
) => (
    log: Log, f: Func<T, U>
) =>
    (input: T, option?: LogOptionType) =>
        wrap(
            logFormatter(option, log),
            f
        )(input);

const f1 = (i: number) => i.toString();
const f2 = (i: string) => i + i;
const g1 = addOption(formatLog1)(wrap1)(console.log, f1);
const g2 = addOption(formatLog2)(wrap1)(console.log, f2);

现在,我可以使用不同的格式选项自由包装现有的一元函数。注意f1的签名是(i :number) => string。通过使用实用程序功能,其签名在g1中变为(i: number, option?: LogOption1) => string

阻止程序是我还有其他包装功能,这些功能不保留输入功能的签名。例如

const wrap2 = <T, U>(log: Log, f: Func<T, U>) => 
    (i: T) => {
       const state = log();
       return [f(i), state];
    }

状态对于在包装函数之间保持一些可选的副作用非常有用。

注意,我在wrap中硬编码了addOption的输出类型。如何改进addOption以允许其他包装功能?

0 个答案:

没有答案