banner
banner
banner
NEWS LETTER

TS-高级类型

Scroll down

交叉类型 &: 多个类型合并为一个类型

  • 『let c = 接口A & 接口B』 的合并类型,c继承A和B的方法又可以使用自身方法

联合类型 |: 规定了几个类型,不同的类型使用不同的方法(和类型保护typeof一起使用)

1
2
3
4
5
6
7
const img = (width: string | number, height: string | number) => {
if(typeof.width === number){}
if(typeof.width === string){}
}

函数的联合类型:
function foo(): a | b {}

类型保护与区分类型

用户自定义的类型保护

1
2
3
4
5
interface Fish { a() } 
interface Flog { c() }
function isFish(pet: Fish | Flog): pet is Fish { // 手动将pet指定为Fish类型
return (<Fish>pet).a !== undefined
}

typeof类型保护

  • 跟联合类型一起使用, 通过判断这个是不是要判断的类型来进入不同代码段

instanceof 类型保护: 通过构造函数来细化类型

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
interface fu { // 父类
getPaddingString(): string
}

class one implements fu { // 子类1实施父类,构造函数为number
constructor(private numSpaces: number) { }
getPaddingString() {...}
}

class two implements fu { // 子类2实施父类,构造函数为string
constructor(private value: string) { }
getPaddingString() {...}
}

function getRandomPadder() { // 定义一个函数,返回这两个子类
return Math.random() < 0.5 ?
new SpaceRepeatingPadder(4) :
new StringPadder(" ");
}
let padder: fu = getRandomPadder(); // 此时Padder有两种类型

if (padder instanceof one) {
// 根据instanceof来判断padder是否等于one的构造函数的类型
padder;
}

可以为null的类型

  • ts中把『null和undefined区分为两种类型』,并且null和undefined可以赋值给任意类型
  • 可选参数和可选属性会自动加上undefined

类型保护和类型断言: 『类型保护用来去除null』

1
2
3
4
5
function  f(sn: string | null): string {
//1.用if...else来判断
return sn || "default" //2.用短路运算符,这样就不可能是null
//3.用类型断言 参数! : return sn! 去除null和undefined
}

类型别名(别名: 参数名)

  • 不会新建一个类型,只是引用
    1
    2
    type Tpost = a & b // Tpost存储了a和b的方法
    // 当遇见a,b的复合类型时直接调用Tpost即可

接口vs类型别名

  • 类型别名不能被extends和implements

字符串字面量类型

1
type A = "B" | "C" | "D" // A的值只能为"B"或"C"或"D"

数字字面量类型

1
type A = 0 | 1 | 2 // A的值只能为0或1或2

可辨识联合

  • 合并单例类型,联合类型,类型保护和类型别名来创建一个叫做『可辨识联合的高级模式』,也叫做『标签联合』『代数数据类型』
    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
    1. 可辨识的特征或标签: 要联合的接口存在相同的属性
    interface a {
    kind : "a",
    width : number
    }
    interface b {
    kind : "b",
    height : number
    }

    2. 联合
    type union = a | b

    3. 使用: 当没有涵盖所有可辨识联合的变化,想让编译器通知使用完整性检查
    function assertNever(x: never): never { // 使用never类型,来检查
    throw new Error("Unexpected object: " + x)
    }
    function f(r: union): string { // 完整性检查的方法一: 指定类型
    switch (r.kind) {
    case "a": return r.width
    case "b": return r.height
    default: return assertNever(r) // 存在除这两种情况的返回assertNever函数
    }
    }

    完整性检查: 当代码变化时,让编译器提醒

索引类型: 通过索引去访问某个值

  • 索引类型查询操作符: 『keyof T』,其值为T上已知的联合属性
    1
    2
    3
    4
    5
    6
    7
    interface Person {
    name: string
    age: number
    }
    let personProps: keyof Person; // 'name' | 'age'
    使用:
    personProps = 'name' // 指的是key值
  • 索引访问操作符: 『T[K]』
    1
    2
    const getProperty = <T, K extends keyof T>(o: T, name: K): T[K] => o[name]
    // o[name]:选择T中的K(name这个key)得到对应key的value

索引类型和字符串索引签名: keyof和 T[K]与字符串索引签名进行交互

  • 如果带有一个字符串索引签名的类型,则 keyof T是 string类型,且T[string]为索引签名的类型
    1
    2
    3
    4
    5
    interface Map<T> {
    [key: string]: T
    }
    let keys: keyof Map<number> // T的类型为number,遍历key,得到的类型为string
    let value: Map<number>['foo'] // T的类型为number,获取当key等于foo的值,值为number类型

映射类型: 新类型以相同的形式去转换旧类型里每个属性

  • Readonly: T中的属性都为只读
  • Partial:T中的属性都为可选
  • Record<K extends string, T>:从T中获取key,T为value的类型
  • Pick<T, K extends keyof T>:从T中选取几个属性K使用 条件类型
  • Exclude<T, U>: 从T中剔除可以赋值给U的类型
  • Extract<T, U>: 提取T中可以赋值给U的类型 条件类型
  • NonNullable: 从T中剔除null和undefined
  • ReturnType: 获取函数返回值类型。
  • InstanceType: 获取构造函数类型的实例类型。
  • Pick<T, Exclude<keyof T, K>>: 实现Omit<T, K>类型
  • ConditionalType<T, U>: 如果T可以赋值给U,则条件为真,类型X将被选择;否则,类型Y将被选择。条件类型
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    type Readonly<T> = { // 只读
    readonly [P in keyof T]: T[P]
    }
    type Partial<T> = { // 可选
    [P in keyof T]?: T[P]
    }
    type PersonPartial = Partial<Person> // 使用
    type ReadonlyPerson = Readonly<Person>

    type Flags = { [K in Keys]: boolean } // k遍历keys,将值添加在flags中,值的类型为boolean

    type Pick<T, K extends keyof T> = { // 类型
    [P in K]: T[P];
    }
    type Record<K extends string, T> = { // 不需要类型
    [P in K]: T;
    }
    type ConditionalType<T, U> =
    T extends U ? X : Y // 条件类型, 如果T可以赋值给U,则条件为真,类型X将被选择;否则,类型Y将被选择。

常用的映射类型:

  • 1.初始化对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    interface IPerson {
    name: string
    age: number
    }
    type Person = Record<keyof IPerson, string>
    const person: Person = {
    name: "moli",
    age: "26"
    }
  • 2.枚举值管理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    enum Color {
    Red="RED"
    Green="GREEN"
    }
    type ColorHex = Recode<Color, string>
    const colorHex: ColorHex = {
    [Color.Red]: "#FF0000",
    [Color.Green]: "#00FF00"
    }
  • 3.字面量
    1
    2
    3
    4
    5
    6
    7
    8
    type Direction = "up" | "right" | "down" | "left"
    type RecordDirect = Record<Direction, number>
    const direction: RecordDirect = {
    up: 1,
    right: 2,
    down: 3,
    left: 4
    }
其他文章
cover
TS-变量声明
  • 24/11/01
  • 11:40
  • TypeScript
cover
TS-安装和编译
  • 24/11/01
  • 11:40
  • TypeScript
目录导航 置顶
  1. 1. 交叉类型 &: 多个类型合并为一个类型
  2. 2. 联合类型 |: 规定了几个类型,不同的类型使用不同的方法(和类型保护typeof一起使用)
  3. 3. 类型保护与区分类型
    1. 3.1. 用户自定义的类型保护
    2. 3.2. typeof类型保护
    3. 3.3. instanceof 类型保护: 通过构造函数来细化类型
  4. 4. 可以为null的类型
    1. 4.1. 类型保护和类型断言: 『类型保护用来去除null』
  5. 5. 类型别名(别名: 参数名)
    1. 5.1. 接口vs类型别名
    2. 5.2. 字符串字面量类型
    3. 5.3. 数字字面量类型
  6. 6. 可辨识联合
  7. 7. 索引类型: 通过索引去访问某个值
    1. 7.1. 索引类型和字符串索引签名: keyof和 T[K]与字符串索引签名进行交互
    2. 7.2. 映射类型: 新类型以相同的形式去转换旧类型里每个属性
    3. 7.3. 常用的映射类型:
请输入关键词进行搜索