让我们说我有一些这样的代码,
const createLogger = ({
dispatch,
frame,
level,
message,
}) => {
dispatch(
actions.debugLog.push({
frame,
level,
message,
}),
)
}
如何在保留命名参数的同时使用此函数?
并像
一样使用它const userLogger = createLogger({
dispatch: useDispatch(),
frame: "userController",
level: "Warning"
// ...potentially other top level keys
})
// user stuff happens
userLogger({ message: "User deleted profile" })()
// later
const adminUserLogger = userLogger({
frame: "adminUserController",
dispatch: adminDispatch
})
用例是这将在我的应用程序的某些区域中调用,从而减少了重复的代码。
期望值会增加(上面只是一个例子),但我也想覆盖某些键。假设我使用一组特定的预设键调用该函数,我想保留这些预设键,但是这次有了一个新的area
。对于更复杂的部分(用于curry的标准用例),此排列的增加。
答案 0 :(得分:0)
(假设您的“工厂功能”(createLogger
)返回一个功能(log
),调用者随后使用该功能记录事件,然后将其称为createLogFunction
)。
(使用TypeScript):
type UseDispatch = 'auto' | true | false;
type Level = 'Warning' | 'Error';
// This interface has all the required and optional named parameters of the original `actions.debugLog.push` function:
interface LogOptions {
readonly dispatch: UseDispatch;
readonly frame: string;
readonly level: Level;
readonly message: string;
[propName: string]: any;
}
type LogFunction = ( opts: Partial<LogOptions> ) => void;
declare actions.debugLog.push: LogFunction; // so `actions.debugLog.push` has the type `LogFunction`.
// This function accepts a subset of `LogOptions` values and returns a new log function that also accepts a subset of LogOptions named parameters
function createLogFunction( factoryOpts: Partial<LogOptions>, innerLogFunc: LogFunction ): LogFunction {
return function( invokeOpts: Partial<LogOptions> ): void {
let combinedOptions: Partial<LogOptions> = {};
combinedOptions = Object.assign( combinedOptions, factoryOpts );
combinedOptions = Object.assign( combinedOptions, invokeOpts );
innerLogFunc( combinedOptions );
};
}
然后您可以像这样使用它:
let originalLogFunction: LogFunction = actions.debugLog.push;
originalLog( { message: "foo", level: 'Warning', dispatch: 'auto' } );
let logWarning = createLogFunction( { level: 'Warning', dispatch: 'auto' }, originalLogFunction );
logWarning( { message: "bar" } );
let noDispatchWarning = createLogFunction( { dispatch: false }, logWarning );
noDispatchWarning ( { message: "qux" } );
答案 1 :(得分:0)
采用slebetman's answer to "How to curry a function across an unknown number of parameters"的基本结构,并合并对象而不是添加数字:
const createLogFunction = options => {
function curryingLogFunction(newOptions) {
if (newOptions !== undefined) {
// add newOptions into options
options = { ...options, ...newOptions };
return curryingLogFunction;
}
// dispatch isn't part of the object pushed to debugLog, so get a
// version of options that doesn't include it
const { dispatch: _, ...optionsWithoutDispatch } = options;
// for the snippet
console.log(options.dispatch, optionsWithoutDispatch);
//options.dispatch(
// actions.debugLog.push(optionsWithoutDispatch),
//);
}
return curryingLogFunction;
}
const logUserAction = createLogFunction({
dispatch: 'useDispatch()', // string for the snippet, function in your code
frame: "userController",
level: "Warning"
// ...potentially other top level keys
});
// user stuff happens
logUserAction({
message: "User deleted profile"
})();
// later
const logAdminAction = createLogFunction({
frame: "adminUserController",
dispatch: 'adminDispatch'
});
logAdminAction({ message: 'message' })({ currying: 'works' })({ frame: 'override defaults' })()