我正在使用FP中的一次函数Once()。当我使用TS时,我需要输入它,但是无法实现此实现。到目前为止,这是我的努力;
const once = <T, U>(fn: (arg: T) => U): () => U | undefined => {
let done = false;
return function(this: (args: T) => U) {
return done ? void 0 : ((done = true), fn.apply(this, arguments));
};
}
我正在将此用于类中的方法:
class CSVOutput extends LogOutput {
private print_headers: (logStat: IStats) => void;
constructor() {
super();
this.print_headers = once((logStat: IStats) => {
console.log(Object.keys(logStat).join(','));
});
}
public print(logStat: IStats) {
this.print_headers(logStat);
console.log(Object.values(logStat).join(','));
}
}
我的tsconfig.json
看起来像
{
"compilerOptions": {
"esModuleInterop": true,
"lib": ["es6", "es7", "es2017"],
"module": "commonjs",
"sourceMap": true,
"target": "es6",
"types": ["node", "mocha"],
"allowJs": true,
"outDir": "./dist",
"preserveSymlinks": true,
"strict": true,
"baseUrl": "."
}
}
我收到TS警告Argument of type 'IArguments' is not assignable to parameter of type '[T]'.
如何在打字稿中正确编写此功能?
答案 0 :(得分:1)
我想我会把它改成这样:
const once = <A extends any[], R, T>(
fn: (this: T, ...arg: A) => R
): ((this: T, ...arg: A) => R | undefined) => {
let done = false;
return function (this: T, ...args: A) {
return done ? void 0 : ((done = true), fn.apply(this, args));
};
};
在这里,我们接受任何函数类型,甚至包括希望设置this
上下文的方法。请注意,我一直使用rest tuple types来表示参数列表。 arguments
的类型在TypeScript中不是很强,可能是因为对于ES2015 +代码,无论如何您都应该使用rest参数。无论如何,返回类型once()
是一个函数,该函数具有与this
相同的fn
上下文和参数列表,并且具有相同的返回类型或undefined
。我认为这种打字方式最适合您:
function yell(x: string) {
return x.toUpperCase() + "!!!!!!!!!";
}
const yellOnce = once(yell);
// const yellOnce: (this: unknown, x: string) => string | undefined
console.log(yellOnce("hello")); // HELLO!!!!!!!!!;
console.log(yellOnce("goodbye")); undefined
好的,希望能有所帮助;祝你好运!