TS:如何推导函数类型
假如存在一个函数如下:
// Watcher 类型,存在一个 on 函数
type Watcher = {
on(event: string, callback: (oldValue: any, newValue: any) => void): void;
};
// watch 函数,返回一个 Watcher 对象
declare function watch(obj: Object): Watcher;
// 创建一个 PersonWatcher 对象
const PersonWatcher = watch({
name: 'Alice',
age: 18,
sex: 'female',
});
// 调用方法
PersonWatcher.on('value', (oldValue, newValue) => {});
在上述代码中,我们只能知道 Watcher 中存在一个 on 函数,接收的 event 参数为 string 类型,callback 函数参数任意,由此引出一个问题:TS 的类型标注到底应该精细到什么程度呢?是详细到每个细节,还是适度就好?
通常来说,这取决于项目的规模和复杂度。类型定义过细会增加开发成本,但适度的类型标注能显著提升代码的可维护性和可靠性。也就是说 TS 的作用是用开发成本换维护成本。
修改为:
// Watcher 类型,存在一个 on 函数
type Watcher<T> = {
on<K extends string & keyof T>(event: `${K}Change`, callback: (oldValue: T[K], newValue: T[K]) => void): void;
};
// watch 函数,返回一个 Watcher 对象
declare function watch<T>(obj: T): Watcher<T>;
const PersonWatcher = watch({
name: 'Alice',
age: 18,
sex: 'female',
address: {},
});
PersonWatcher.on('nameChange', (oldValue, newValue) => {});
PersonWatcher.on('ageChange', (oldValue, newValue) => {});
PersonWatcher.on('addressChange', (oldValue, newValue) => {});
代码解释:
1、Watcher<T> 类型:Watcher 是一个泛型类型,接受类型参数 T。这个类型包含一个 on 方法,用于监听对象属性的变化。
1)K extends string & keyof T:这里 K 是泛型,表示 T 对象中的某个属性的键名,且必须是字符串类型。
2)event:参数是模版字符串类型,要求传入的事件名称必须符合 "属性名 + Change" 的格式。比如:如果 T 有属性 name,那么 event 必须是 nameChange。
3)callback:函数用于处理变化事件,参数类型与被监听属性的类型一致,即 T[K],表示对象的属性值。
2、watch 函数:接受一个对象 obj 作为参数,返回 Watcher<T> 对象,其中 T 是 obj 的类型。
由此,这个函数的类型就书写的很详细啦!简单举个 🌰 阐述一下,在开发中,还需要具体问题具体对待。