• 类型保护就是一些表达式,他们在编译的时候就能通过类型信息确保某个作用域内变量的类型
  • 类型保护就是能够通过关键字判断出分支中的类型

    typeof 类型保护

    1. function fn(a:string|number): void {
    2. if (typeof a == 'number') {
    3. console.log('number')
    4. } else {
    5. console.log('string')
    6. }
    7. }

    instanceof 类型保护

    ```typescript class Animal { } class Dog extends Animal { } class Cat extends Animal { }

function getName(animal: Animal): Animal { if (animal instanceof Dog) { return ‘dog’; } else { return ‘cat’; } }

  1. <a name="oKJL8"></a>
  2. # null 保护
  3. 如果开启了strictNullChecks选项,那么对于可能为null的变量不能调用它上面的方法和属性
  4. ```typescript
  5. function getStr(str: string | null) {
  6. str = str || '';
  7. return str;
  8. }

链判断运算符

  • 链判断运算符是一种先检查属性是否存在,再尝试访问该属性的运算符,其符号为 ?.
  • 如果运算符左侧的操作数 ?. 计算为 undefined 或 null,则表达式求值为 undefined 。否则,正常触发目标属性访问,方法或函数调用。

    1. a?.b; //如果a是null/undefined,那么返回undefined,否则返回a.b的值.

    链判断运算符 还处于 stage1 阶段,TS 也暂时不支持

    可辨识的联合类型

  • 就是利用联合类型中的共有字段进行类型保护的一种技巧

  • 相同字段的不同取值就是可辨识
    1. interface WarningButton {
    2. class: 'warning';
    3. text1: '修改';
    4. }
    5. interface DangerButton {
    6. class: 'danger';
    7. text2: '删除';
    8. }
    9. type Button = WarningButton | DangerButton;
    10. function getButton(button: Button) {
    11. if (button.class == 'warning') {
    12. console.log(button.text1);
    13. }
    14. if (button.class == 'danger') {
    15. console.log(button.text2);
    16. }
    17. }
    上面的接口我们声明的好像是一个对象。。。
    1. interface User {
    2. username: string
    3. }
    4. type Action = {
    5. type:'add',
    6. payload:User
    7. } | {
    8. type: 'delete'
    9. payload: number
    10. }
    11. const UserReducer = (action: Action) => {
    12. switch (action.type) {
    13. case "add":
    14. let user: User = action.payload;
    15. break;
    16. case "delete":
    17. let id: number = action.payload;
    18. break;
    19. default:
    20. break;
    21. }
    22. };

    in操作符

    in 运算符可以被用于参数类型的判断 ```typescript interface Bird { swing: number }

interface Dog { leg: number } function getNumber(x: Bird | Dog) { if (‘swing’ in x) { return x.swing } return x.leg; }

  1. <a name="JT5qD"></a>
  2. # 自定义的类型保护
  3. - TypeScript 里的类型保护本质上就是一些表达式,它们会在运行时检查类型信息,以确保在某个作用域里的类型是符合预期的
  4. - type is Type1Class就是类型谓词
  5. - 谓词为 parameterName is Type这种形式,parameterName必须是来自于当前函数签名里的一个参数名
  6. - 每当使用一些变量调用isType1时,如果原始类型兼容,TypeScript会将该变量缩小到该特定类型
  7. ```typescript
  8. interface Person {
  9. leg: number
  10. }
  11. interface Dog {
  12. leg: number
  13. }
  14. function isPerson(x: Person | Dog): x is Person {
  15. return x.leg == 2;
  16. }
  17. function getType(x: Person | Dog) {
  18. if (isPerson(x)) {
  19. console.log('这是个人');
  20. } else {
  21. console.log('这是条狗');
  22. }
  23. }
  24. const p: Person = { leg: 2 };
  25. getType(p); // '这是个人'

unknown

  • TypeScript 3.0 引入了新的unknown 类型,它是 any 类型对应的安全类型
  • unknown 和 any 的主要区别是 unknown 类型会更加严格:在对 unknown 类型的值执行大多数操作之前,我们必须进行某种形式的检查。而在对 any 类型的值执行操作之前,我们不必进行任何检查

    any

  • 在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的 顶级类型 (也被称作 全局超级类型)。

  • TypeScript允许我们对 any 类型的值执行任何操作,而无需事先执行任何形式的检查 ```typescript let value: any;

value = true; // OK value = 42; // OK value = “Hello World”; // OK value = []; // OK value = {}; // OK value = Math.random; // OK value = null; // OK value = undefined; // OK

let value: any; value.foo.bar; // OK value.trim(); // OK value(); // OK new value(); // OK

  1. <a name="LF0ii"></a>
  2. ## unknown 类型
  3. - 就像所有类型都可以被归为 any,所有类型也都可以被归为 unknown。这使得 unknown 成为 TypeScript 类型系统的另一种顶级类型(另一种是 any)
  4. - 任何类型都可以赋值给unknown类型
  5. ```typescript
  6. let value: unknown;
  7. value = true; // OK
  8. value = 42; // OK
  9. value = "Hello World"; // OK
  10. value = []; // OK
  11. value = {}; // OK
  12. value = Math.random; // OK
  13. value = null; // OK
  14. value = undefined; // OK
  15. value = new TypeError(); // OK

unknown类型只能被赋值给any类型和unknown类型本身

  1. let value: unknown;
  2. let value1: unknown = value; // OK
  3. let value2: any = value; // OK
  4. let value3: boolean = value; // Error
  5. let value4: number = value; // Error
  6. let value5: string = value; // Error
  7. let value6: object = value; // Error
  8. let value7: any[] = value; // Error
  9. let value8: Function = value; // Error

缩小 unknown 类型范围

  • 如果没有类型断言或类型细化时,不能在unknown上面进行任何操作
  • typeof
  • instanceof
  • 自定义类型保护函数
  • 可以对 unknown 类型使用类型断言
    1. const value: unknown = "Hello World";
    2. const someString: string = value as string;

    联合类型中的 unknown 类型

    在联合类型中,unknown 类型会吸收任何类型。这就意味着如果任一组成类型是 unknown,联合类型也会相当于 unknown
    1. type UnionType1 = unknown | null; // unknown
    2. type UnionType2 = unknown | undefined; // unknown
    3. type UnionType3 = unknown | string; // unknown
    4. type UnionType4 = unknown | number[]; // unknown

    交叉类型中的 unknown 类型

    在交叉类型中,任何类型都可以吸收 unknown 类型。这意味着将任何类型与 unknown 相交不会改变结果类型
    1. type IntersectionType1 = unknown & null; // null
    2. type IntersectionType2 = unknown & undefined; // undefined
    3. type IntersectionType3 = unknown & string; // string
    4. type IntersectionType4 = unknown & number[]; // number[]
    5. type IntersectionType5 = unknown & any; // any

    never是unknown的子类型

    Snip20220327_499.png

    keyof unknown 等于never

    image.png

    只能对unknown进行等或不等操作,不能进行其它操作

    映射类型

    ```typescript type getType = {

};

let obj = { a: 1, b: ‘’, c: false }; type c = getType

  1. 我们查看下 c 是什么类型?<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/21397267/1648349385443-da184929-09e0-4936-9975-b8acc9daddb2.png#clientId=u43411b2e-3ff6-4&from=paste&id=u13464b23&margin=%5Bobject%20Object%5D&name=image.png&originHeight=263&originWidth=560&originalType=binary&ratio=1&size=48607&status=done&style=none&taskId=uc19f7b97-90a4-4910-8118-8dd3f6d7859)<br />如果映射类型遍历的时候是unknown,不会映射属性
  2. ```typescript
  3. type getType<T> = {
  4. [P in keyof T]:number
  5. }
  6. type t = getType<unknown>;

结果如下,可以看到 t 是一个空对象:
image.png