我有一个更高阶的函数,例如像vanilla JS这样:
function log(fn) {
return (...args) => {
console.log("Calling", fn.name);
return fn(...args);
}
}
并像这样使用:
let name;
const setName = log((newName) => {
name = newName;
});
setName("Hello"); // output "Calling setName"
如何在TS中正确键入此类,以便setName
具有正确的函数签名?含义:
setName("hello") // OK
setName() // Error, missing arg
setName(123) // Error, number not string
到目前为止,我提出的是:
function log<F extends Function>(fn: F): F {
return (...args: any[]) => {
console.log("Calling", fn.name);
return fn(...args);
}
}
let name;
const setName = log((newName: string) => {
name = newName;
});
哪种方式按我想要的方式工作(我在setName
上得到参数类型检查)但是我在log
函数返回时遇到编译错误:
错误:TS2322:输入&#39;(... args:any [])=&gt;任何&#39;不能分配给&#39; F&#39;。
即使我使用<F extends (...args: any[]) => any>
,我也会遇到同样的错误。基本上,我不知道如何使返回的函数满足泛型F
。
我该怎么做?
答案 0 :(得分:2)
Function overloads。这是一种将定义与实现分开的方法:
function log<F extends Function>(fn: F): F
function log(fn: Function) {
return (...args) => {
console.log("Calling", fn.name);
return fn(...args);
}
}
我喜欢重载版本,因为当模块作为预编译的NPM包分发时,它有助于生成TypeScript定义。
as F
类型Function
太宽。您的包装函数必须是以下的子类型:(...args: any[]) => any
。
您可以使用as F
来说明TypeScript对返回的函数有信心:
function log<F extends (...args: any[]) => any>(fn: F): F {
return ((...args: any[]) => {
console.log("Calling", fn.name);
return fn(...args);
}) as F
}
as any
相同的实现,但我们可以使用Function
和as any
代替(...args: any[]) => any
和as F
(请参阅路易斯的回答)。
答案 1 :(得分:2)
您可以做出的最直接的修改是将返回值的类型强制为/**
* Find the root {@code WebApplicationContext} for this web app, typically
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
* <p>Will rethrow an exception that happened on root context startup,
* to differentiate between a failed context startup and no context at all.
* @param sc ServletContext to find the web application context for
* @return the root WebApplicationContext for this web app, or {@code null} if none
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*/
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
:
any
这个编译文件,执行此操作后,您的function log<F extends Function>(fn: F): F {
return ((...args: any[]) => {
console.log("Calling", fn.name);
return fn(...args);
}) as any;
}
函数将与传递给setName
的函数具有相同的签名。