上示例
一个简单的节流函数
function debounce(f: Function, delay: number = 3000) {
let d = 0;
return function (...arg: any) {
if (d + delay > Date.now()) return;
d = Date.now();
f(...arg);
};
}
// [ts] const log: (...arg: any) => void
const log = debounce((...arg: string[]) => {
console.log(...arg);
});
ts 提示的居然不是 的参数集居然不是 string[]
,这并不是我们想要的,而且,而且它还是 any,直接等于没提示
不要急,不要慌,这里还有解决的方法
以下,我们借用泛形在重写一遍 debounce
function debounce<T extends unknown[]>(f: (...arg: T) => unknown, delay: number = 3000) {
let date = 0;
return function (...arg: T) {
if (date + delay > Date.now()) return;
date = Date.now();
f(...arg);
};
}
// [ts] const log: (str1: string, str2?: string, str3?: string) => void
const log = debounce((str1: string, str2?: string, str3?: string) => {
console.log(str1, str2, str3);
});
我们使用泛形后,参数和类型都推断了出来,在使用 log 时,就可以获得良好的参数提示,而不是 any
泛形使用
以上的 debounce 其实还有另外一种使用方式
const log = debounce<[str1: string, str2?: string, str3?: string]>((str1, str2, str3) => {
console.log(str1, str2, str3);
});
它其实和上面的方式是一毛一样的,不同的是,它在使用 debounce 时,直接传了[str1: string, str2?: string, str3?: string]
什么,传(chuan)
了?
没错,就是传了。
泛形有一些函数参数的特点
interface Person<AGE> {
age: AGE;
// ...
}
const person: Person<string> = {
age: '19',
};
const person1: Person<number> = {
age: 19,
};
interface Person<AGE = number> {
age: AGE;
}
// 不使用默认值
const person: Person<string> = {
age: '19',
};
// 使用默认值
const person1: Person = {
age: 19,
};
interface Person<AGE> {
age: AGE;
}
// [ts] const person: { age: number; }
const person = {
age: 18,
};
泛形使用方式
// interface
interface Person<N, A> {
name: N;
age: A;
}
// type
type Person1<N, A> = {
name: N;
age: A;
};
// 函数
function Person2<N, A>(name: N, age: A) {}
// 类
class Person3<N, A> {
name: N;
age: A;
constructor() {}
say(name: N, age: A) {}
}
误区
错误,泛型不可以和 es6 一样使用 ...
来聚合多个参数(或许以后会吧)
interface Person<...ARGS> {}
函数重载是一个强大的功能,在现有的流行库中有很多都使用上了
直接上示例吧
有时候我们需要一个这样的函数,在传参时设置该属性,在没传时则返回改属性。
如下
// 有参数时,则设置innerHTML参数,否则获取改属性
function html(content?: string): string | undefined {
if (content) {
el.innerHTML = content;
} else {
return el.innerHTML;
}
}
但是,有了重载只有,我们可以这样写
/**
* 获取innerHTML属性
*/
function html(): string;
/**
* 设置innerHTML属性
*/
function html(content: string): void;
function html(content?: string): string | void {
if (content) {
el.innerHTML = content;
} else {
return el.innerHTML;
}
}
// [ts] function html(): string (+1 overload)
// 获取innerHTML属性
html();
// [ts] function html(content: string): void (+1 overload)
// 设置innerHTML属性
html('123123');
如果 IDE 支持显示函数上面的注释,甚至还可以在分不同的重载显示不同注释提示
重载是什么
重载可以说时对函数输入输出的各种可能做不同的枚举,赋予使用时明确的提示
可以看上方示例,最下面的 function html(content?: string): string | void
我们可以叫做实现,而它上面两个可以叫做重载函数,上面有两个,也就是说,html
有两个重载函数
实现:指真实的函数,真实的函数需要把所有重载的函数参数在这里写一遍
重载函数:要把函数参数的每一种传参数量和类型以及返回类型列举出来
重载函数每个都可以有不同的泛形,前提是你能方便的处理好实现时的输出
什么时候使用重载
参数长度不同
且函数输出类型不同
时
参数类型不同
且参数类型不同
和函数输出类型不同
时