# 高级类型二
WARNING
this 类型
索引类型
- 索引类型查询操作符
- 索引访问操作符
映射类型
- 基础
- 由映射类型进行推断
- 增加或移除特定修饰符
- keyof 和映射类型的升级
- 元祖和数组上的映射类型
条件类型
- 基础
- 分布式条件类型
- 条件类型的类型推断 -- infer
- 预定义条件类型
this 类型
class Counter {
constructor(public count: number = 0) {
}
add (value: number) {
this.count += value
return this
}
subtract (value: number) {
this.count -= value
return this
}
}
let counter1 = new Counter(10)
console.log(counter1, 'counter1')
// 链式调用
console.log(counter1.add(3).subtract(2))
class PowCounter extends Counter {
constructor(public count: number) {
super(count);
}
pow (value: number) {
this.count = this.count ** value
return this
}
}
let powCounter = new PowCounter(2)
console.log(powCounter.pow(3).add(1).subtract(3))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
索引类型: 索引类型查询 keyof,索引类型访问
interface InfoAdvance {
name: string,
age: number
}
let infoAd1: keyof InfoAdvance
infoAd1 = 'name'
infoAd1 = 'age'
// infoAd1 = 'sex' // 提示没有这个属性
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
function getValue<T, K extends keyof T> (obj: T, names: K[]): T[K][] {
return names.map(n => obj[n])
}
let infoData = {
name: 'xiaoyu',
age: 19
}
let values = getValue(infoData, ['name', 'age'])
console.log(values, 'values---') // ['xiaoyu', 19]
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
索引访问操作符 []
interface InfoAdvance2 {
name: string,
age: number
}
type NameTypes = InfoAdvance2['name']
1
2
3
4
5
6
7
2
3
4
5
6
7
interface Objs<T> {
[key: number]: T
}
// keys 是 objs 属性名的类型 keys 为 number
let keys: keyof Objs<number>
1
2
3
4
5
6
2
3
4
5
6
映射类型
interface Info1 {
age: number,
name: string,
sex: string
}
// interface ReadOnlyType {
// readonly age: number
// }
type ReadOnlyType<T> = {
readonly [P in keyof T]?: T[P] // 对属性名的遍历
}
// 循环给每个属性都添加 readonly
type ReadOnlyType1 = ReadOnlyType<Info1>
// 所有的属性都添加了 readonly
let info11: ReadOnlyType1 = {
age: 19,
name: 'xiaoyu',
sex: 'nv'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TS 内置了Readonly (只读属性) 、Partial (可选属性)
type ReadOnlyType1 = Readonly<Info1>
type ReadOnlyType1 = Partial<Info1>
1
2
3
2
3
Pick 、 Record
type Pick<T, K extends keyof T> = {
[P in K]: T[P]
}
1
2
3
2
3
type Record<K extends keyof any, T> = {
[P in K]: T;
};
1
2
3
2
3
interface Info3 {
name: string,
age: number,
address: string
}
let info3: Info3 = {
name: 'xiaoyu',
age: 18,
address: 'beijing'
}
function pickfn<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
let res: any = []
keys.map((key) => {
res[key] = obj[key]
})
return res
}
let nameAddress = pickfn(info3, ['name', 'address'])
console.log(nameAddress, 'nameAddress') // [name: 'xiaoyu', address: 'beijing']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Record 使对象中的每个属性转化成其他值的场景
function mapObj<K extends string | number, T, U> (obj: Record<K, T>, f: (x: T) => U): Record<K, U> {
let res: any = {}
for (let key in obj) {
res[key] = f(obj[key])
}
return res
}
let names1 = {
0: 'hello', // 把 hello 转成了 长度 5
1: 'world',
2: 'bye'
}
let lengths = mapObj(names1, (s) => s.length)
console.log(lengths, 'lengths') // {0: 5, 1: 5, 2: 3}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type Proxy<T> = {
get(): T;
set(value: T): void
}
type Proxify <T> = {
[P in keyof T] : Proxy<T[P]>
}
function proxify<T> (obj: T): Proxify<T> {
let result = {} as Proxify<T>
for (let key in obj) {
result[key] = {
get: () => obj[key],
set: (value) => obj[key] = value
}
}
return result
}
let props = {
name: 'xiaoyu',
age: 18
}
let proxyProps = proxify(props)
console.log(proxyProps, 'proxyProps')
proxyProps.name.get()
proxyProps.name.set('你好')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

逆向拆包
function unproxify <T>(t: Proxify<T>): T {
let result = {} as T
for (let k in t) {
result[k] = t[k].get()
}
return result
}
let originProps = unproxify(proxyProps)
console.log(originProps, 'origin') // {name: '你好', age: 18}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
增加(+)或移除(-)特定修饰符
interface Info1 {
age: number,
name: string,
sex: string
}
type ReadOnlyType<T> = {
+readonly [P in keyof T]: T[P] // 对属性名的遍历
}
// 循环给每个属性都添加 readonly
type ReadOnlyType1 = ReadOnlyType<Info1>
let info11: ReadOnlyType1 = {
age: 19,
name: 'xiaoyu',
sex: 'nv'
}
type RemoveReadonlyInfo2 <T> = {
// -readonly 表示去掉readonly -? 表示去掉可选符号?
-readonly [P in keyof T]-?: T[P]
}
// 把所有的readonly去掉
type InfoWithoutReadonly = RemoveReadonlyInfo2<Info1>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
keyof 的升级
const stringIndex = 'a'
const numberIndex = 1
const symbolIndex = Symbol('hh')
type Objs2 = {
[stringIndex]: string,
[numberIndex]: number,
[symbolIndex]: symbol
}
type keysType = keyof Objs2
type ReadonlyTypes <T> = {
readonly [P in keyof T]: T[P]
}
let objtype3: ReadonlyTypes<Objs2> = {
a: 'aa',
1: 11,
[symbolIndex]: Symbol()
}
// objtype3.a = '00' // 只读属性不可以赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
元祖和数组上的映射类型
type MapToPromise<T> = {
[K in keyof T]: Promise<T[K]>
}
type Tuple = [number, string, boolean]
type promiseTuple = MapToPromise<Tuple>
let tuple11: promiseTuple = [
new Promise((resolve) => resolve(1)),
new Promise((resolve) => resolve('22')),
new Promise((resolve) => resolve(true)),
]
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
unknown 顶级类型
- 任何类型都可以赋值给
unknown
let value11: unknown
value11 = 1
value11 = '2'
1
2
3
2
3
- 如果没有类型断言或基于控制流的类型细化时,
unknown不可以赋值给其他类型,此时他只能赋值给unknown和any类型
let value22: unknown
// let value33: string = value22 // 提示不能赋值
value11 = value22
1
2
3
2
3
- 如果没有类型断言或基于控制流的类型细化时, 不能在他上面进行任何操作
let value44: unknown
// value44 += 1 // 不能运算
1
2
2
unknown与其他任何类型组成的交叉类型,最后都等于其他类型
type type1 = string & unknown // string
type type2 = unknown & string[] // string[]
1
2
2
unknown与任何其他类型(除去 any)组成的联合类型,都等于 unknown 类型
type type3 = unknown | string // unknown
type type4 = any | unknown // any
type type5 = number[] | unknown // unknown
1
2
3
2
3
never是unknown的子类型
type type6 = never extends unknown ? true : false // true
1
keyof unknown等于类型 never
type type7 = keyof unknown // never
1
- 只能对
unknown进行等或不等操作
let val1: unknown
let val2: unknown
val1 === val2
val1 !== val2
val1 += val2 // 不能运算
1
2
3
4
5
2
3
4
5
unknown类型的值不能访问属性,也不能作为函数调用,不能作为类创建实例
let val1 : unknown
val1() // 报错
new val1() // 报错
1
2
3
4
2
3
4
- 使用映射类型时如果遍历的是
unknown,则不会映射任何属性
type Types1<T> = {
[P in keyof T]: number
}
type type8 = Types1<any>
type type9 = Types1<unknown>
1
2
3
4
5
2
3
4
5


条件类型 T extends U ? X : Y
type Types2<T> = T extends string ? string : number
let index1: Types2<'a'> // string
let index2: Types2<1> // number
1
2
3
2
3
分布式条件类型
当待检测类型是联合类型的时候, 该条件被称为分布式条件类型
type TypeName<T> = T extends any ? T : never
type type10 = TypeName<string | number> // string | number
1
2
2
type TypeName2<T> =
T extends string ? string :
T extends number ? number :
T extends boolean ? boolean :
T extends undefined ? unknown :
object
type type11 = TypeName2<string[]> // object
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
分布式条件的应用例子
type Diff<T, U> = T extends U ? never : T
type test = Diff<string | number | boolean, undefined | number> // string | boolean
// string | number | boolean 分别判断是否是 undefined | number 的子类型
// string 是否是 undefined | number 子类型 , 不是 -> 返回 string
// number 是否是 undefined | number 子类型 , 是 -> 返回 never
// boolean 是否是 undefined | number 子类型 , 不是 -> 返回 boolean
1
2
3
4
5
6
7
2
3
4
5
6
7
条件类型和映射类型结合
type type12<T> = {
[K in keyof T]: T[K] extends Function ? K : never
} [keyof T] // 返回不为 never的类型
interface Part {
id: number,
name: string,
subparts: Part[],
undatePart(newName: string): void
}
type Test1 = type12<Part> // undatePart
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
条件类型的类型推断 infer
// 传进来的如果是数组,就取数组里元素的类型,如果不是数组直接取当前类型
type Type13<T> = T extends any[] ? T[number] : T
type test2 = Type13<string[]> // string
type test3 = Type13<string>
// 使用 infer
type Type14<T> = T extends Array<infer U> ? U : T
type test4 = Type14<string[]> // string U就是数组元素的类型
type test5 = Type14<number> // number
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
预定于内置类型 Exclude<T, U>
type Type15 = Exclude<'a' | 'b' | 'c', 'a' | 'b'> // c
type Type16 = Exclude<'a' | 'b' | 'c', 'a'> // b | c
1
2
2
Extract<T, U> 选出T中可以赋值给U的类型
type Type17 = Extract<'a' | 'b' | 'c', 'c' | 'b'> // b | c
1
NonNullable<T> 可以从T中去掉 null 和 undefined
type Type18 = NonNullable<string | number | null | undefined> // string | number
1
ReturnType<T> 获取函数返回值类型
type Type19 = ReturnType<() => string> // string
1
InstanceType<T> 获取构造函数实例类型
// 源码实现
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
1
2
2
class AClass {
constructor() {
}
}
type T1 = InstanceType<typeof AClass>
type T2 = InstanceType<any>
type T3 = InstanceType<never>
type T4 = InstanceType<string> // 报错
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
← 高级类型一 ES6和Node中的模块 →