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
}

类型别名(别名: 参数名),不会新建一个类型,只是引用

  • type Tpost = a & b,Tpost是存储了a和b的方法,下次调用直接使用Tpost节省代码量
  • 接口vs类型别名

    • 类型别名不能被extends和implements
  • 字符串字面量类型

    • type A = “B” | “C” | “D” // A的值只能为B或C或D
  • 数字字面量类型

    • 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
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 —> 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>类型
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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;
    }
  • 常用:
    • 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
      }

条件类型

  • type ConditionalType<T, U> = T extends U ? X : Y // 如果T可以赋值给U,则条件为真,类型X将被选择;否则,类型Y将被选择。
  • Pick<T, K extends keyof T>:从T中选取几个属性K使用
  • Extract<T, U>: 提取T中可以赋值给U的类型
其他文章
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. 条件类型
请输入关键词进行搜索