由某个
interface实现可选一个新的可选接口
- 假如有这么一块代码
interface Article {
title: string;
content: string;
author: string;
date: Date;
readcount: number;
}
interface CreateArticleOptions {
title: string;
content: string;
author?: string;
date?: Date;
readcount?: number;
}
需求是将部分字段变为可选
- 优化
CreateArticleOptions
/*
& 联合
Omit 过滤,缺省的意思
Pick 挑选
Partial 设置为可选
*/
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
/*
分析 Optional<Article, 'author' | 'date' | 'readcount'>
1. 使用Omit 去掉了Article中的'author' | 'date' | 'readcount' 剩余{title, content}
2. 使用Pcik<T, K>拿到去掉了Article中的'author' | 'date' | 'readcount' 为{author, date, readcount}
3. 使用Partial将{author, date, readcount}变为可选{author?, date?, readcount?}
4. 使用 & 求交叉类型 {title, content} & {author?, date?, content?}
*/
type CreateArticleOptions = Optional<Article, 'author' | 'date' | 'readcount'>;
- 结果
从字段到函数的推导
- 假如有这样的一个代码块
type Watcher = {
on(
eventName: string,
callback: (oldValue: any, newValue: any) => void
): void;
}
declare function watch(obj: object): Watcher;
const personWatcher = watch({
firstName: 'John',
lastName: 'Doe',
age: 36
});
personWatcher.on('ageChanged', (oldValue: any, newValue: any) => {});
优化过程
- 优化
eventName
type Watcher = {
on(
eventName: `${'firstName' | 'lastName' | 'age'}Changed`,
callback: (oldValue: any, newValue: any) => void
): void;
}
declare function watch(obj: object): Watcher;
const personWatcher = watch({
firstName: 'John',
lastName: 'Doe',
age: 36
});
personWatcher.on('ageChanged', (oldValue: any, newValue: any) => {});
这么写局限性较大,继续优化
// 直接写keyof T 报错:不能将类型“symbol”分配给类型
// “string | number | bigint | boolean | null | undefined”。
//因为T的键可能是symbol
// string & keyof T --> 'a'|'b'|symbol & string --> 'a'|'b'
type Watcher<T> = {
on<K extends string & keyof T>(
// eventName: `${string & keyof T}Changed`,
eventName: `${K}Changed`,
callback: (oldValue: T[K], newValue: T[K]) => void
): void;
}
declare function watch<T>(obj: T): Watcher<T>;
const personWatcher = watch({
firstName: 'John',
lastName: 'Doe',
age: 36,
sex: 'boy'
});
// personWatcher.on<'age'>('ageChanged', (oldValue, newValue) => {});
personWatcher.on('firstNameChanged', (oldValue, newValue) => {
});
做到了约束eventName和callback形参类型