我想用typescript写一个debounce函数。我的代码如下:
function debounce(fn: Function, time: number): Function {
// ...
}
然后,我的eslint
告诉我不要使用Function
作为类型。以下是原文:
不要使用Function
作为类型。Function
类型接受任何类似函数的值。它在调用函数时不提供类型安全,这可能是bug的常见来源。它还接受类声明之类的东西,这些声明将在运行时抛出,因为它们不会被new
调用。
如果你希望函数接受某些参数,你应该显式地定义函数的形状。
这就是问题所在,有什么建议吗?
==================== 一些更新 ==================================
如果使用javascript,我的代码将是:
function debounce(fn, time) {
let timer
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), time)
}
}
给定您的实现,从debounce()
返回的函数不返回有用的结果;这意味着我们不关心fn
参数的返回类型是什么。在这种情况下,我可能会使debounce()
成为一个泛型函数,其类型参数A
作为与fn
的参数相对应的rest元组。这样的:
function debounce<A extends any[]>(fn: (...a: A) => void, time: number) {
let timer: number;
return function (...args: A) {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), time)
}
}
类型(...a: A) => void
是一个函数类型表达式,意思是"该函数的参数数组为A
类型,并且返回void
,因此它的返回类型将被忽略"。
如果你检查debounce()
的类型,它看起来像这样:
/* function debounce<A extends any[]>(
fn: (...a: A) => void, time: number
): (...args: A) => void */
它接受一个(...a: A) => void
类型的函数,并返回一个相同类型的函数。
让我们确保它工作:
function log(x: string) {
console.log(x);
}
const debouncedLog = debounce(log, 1000);
debouncedLog("hello");
debouncedLog(100); // error, doesn't accept a number
debouncedLog("there");
// just "there" is logged
你可以看到编译器抱怨debouncedLog(100)
,因为100
不能赋值给string
,而其他调用可以正常工作。
Playground链接到代码
我建议你看看TypeScript的实用程序类型,比如Parameters<Type>
和ThisParameterType<Type>
。他们是我用于防反跳的打印稿实现函数使返回的函数匹配输入函数的签名。
至于我如何指定函数参数,我使用了这样的泛型:
const debounce = function<T extends (...args: any) => any> (fn: T, delay: number) {