TS学习--将interface部分字段变为可选

125 阅读1分钟

由某个interface实现可选一个新的可选接口

  1. 假如有这么一块代码
interface Article {
  title: string;
  content: string;
  author: string;
  date: Date;
  readcount: number;
}

interface CreateArticleOptions {
  title: string;
  content: string;
  author?: string;
  date?: Date;
  readcount?: number;
}

需求是将部分字段变为可选

  1. 优化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'>;
  1. 结果

image.png

从字段到函数的推导

  1. 假如有这样的一个代码块
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) => {});

优化过程

  1. 优化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) => {

});

做到了约束eventNamecallback形参类型

image.png

image.png