开坑第一天!Typescript类型基本运算!(我为什么不去github写博客呢。。

呀哈喽!我是saber2pr。

(最近在做的几件事情:

1. 看《家有女友

2. 写@saber2pr/nana

 


 

Typescript 类型基本运算

 

(博客园的代码块没有typescript啊

首先有这么一个类型

type Test = {
  a: string
  b: number
}

怎么给它增加一个属性呢?

 


 

 

在解决这个问题之前,先了解一下typescript的基础操作

1. 获取一个类型的所有属性集合(union)

type keys = keyof Test // "a" | "b

keyof 运算符用来获取一个类型的所有属性集合

 

2. 扩增union

type result = keys | 'c' // "a" | "b" | "c"

这个很简单。

 

3. 遍历union

有了keys就可以遍历了

type result = {
  [P in keys]: Test[P]
}

 这段代码相当于如下伪代码

var result = keys.map(P => Test[P])

应该和你想的差不多,就是把Test类型映射为另外一种类型

 

4. 条件语句

type isExtendsA = keys extends 'a' ? 'yes' : 'no' // "no"
type isExtendsAB = keys extends 'a' | 'b' ? 'yes' : 'no' // "yes"

extends在typescript里被称作条件语句,用来判断一个类型是否是指定类型的子集

 


 

有以上基础就可以实现我们的需求了:

比如给Test类型增加一个属性c,类型是Function类型

首先先获取它的union

type Test = {
  a: string
  b: number
}

type keys = keyof Test // "a" | "b"

 

给keys增加一个"c"

type keys_added_c = keys | 'c' // "a" | "b" | "c"

 

然后遍历这个新的union

type result = { 
  [P in keys_added_c]: any 
}
// {a: any;b: any;c: any;}

成功增加了一个属性c,但是所有属性的类型都丢失了。

所以应该用条件语句判断P,如果是Test原本有的属性,就保留原来的类型,否则指定新类型比如Function

type result = { 
  [P in keys_added_c]: P extends keys? Test[P]: Function
}
// {a: string;b: number;c: Function;}

 

把上述过程封装一下就是:

type Test = {
  a: string
  b: number
}
/**
 * get the keys which extends Filter
 */
export type GetKeys<T, Filter = any> = {
  [P in keyof T]: T[P] extends Filter ? P : never
}[keyof T]
/**
 * add a key to keys
 */
export type AddKey<T, K> = GetKeys<T> | K
/**
 * add a key to type
 */
export type Add<Target, K extends string | number | symbol, T = any> = {
  [P in AddKey<Target, K>]: P extends keyof Target ? Target[P] : T
}

type result = Add<Test, 'c', Function> // {a: string;b: number;c: Function;}

 


 

 关于Typescript还有很多有趣的特性,有时间再更新这篇博客。

 

我也整理了一些常用的Ts工具类型在github上,欢迎star

@saber2pr/ts-lib

 也可以直接下载npm包尝试 > npm i @saber2pr/ts-lib

posted @ 2019-04-13 19:50  saber2pr  阅读(65)  评论(0)    收藏  举报