我想知道我是否尝试设计一种替代现有功能签名的功能是否有效。我正在使用打字稿,并希望保持打字安全。
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
以允许其他包装功能?