TypeScript-类型保护

  • 对于联合类型的变量,在使用时如何确切告诉编译器它是哪一种类型
  • 通过 类型断言 或者 类型保护

如下我写了一个示例代码,就是一个 getRandomValue 函数,通过生成的随机数,来决定返回的是 string 还是 number 类型,那么我想如果是 string 类型则调用 .length 属性,如果是数字就调用 toFixed

let getRandomValue = (): (string | number) => {
    let num = Math.random();
    return (num >= 0.5) ? 'abc' : 123.123;
}

let value = getRandomValue();
console.log(value);

那么就由此得来如下这么一段代码:

let getRandomValue = (): (string | number) => {
    let num = Math.random();
    return (num >= 0.5) ? 'abc' : 123.123;
}

let value = getRandomValue();
console.log(value);

if (value.length) {
    console.log(value.length);
} else {
    console.log(value.toFixed());
}

但是通过我所编写的代码在编译器当中是会报错的,那么就来看看通过 类型断言类型保护 来解决该问题吧。

通过类型断言:

let getRandomValue = (): (string | number) => {
    let num = Math.random();
    return (num >= 0.5) ? 'abc' : 123.123;
}

let value = getRandomValue();
console.log(value);

if ((value as string).length) {
    console.log((value as string).length);
} else {
    console.log((value as number).toFixed());
}

如上虽然通过 类型断言 可以确切的告诉编译器当前的变量是什么类型,但是每一次使用的时候都需要手动的告诉编译器, 这样比较麻烦, 冗余代码也比较多,那么这个时候就出现了如下的类型保护的编写方式来进行实现了。

通过类型保护:

let getRandomValue = (): (string | number) => {
    let num = Math.random();
    return (num >= 0.5) ? 'abc' : 123.123;
}

let value = getRandomValue();
console.log(value);

function isString(value: (string | number)): value is string {
    return typeof value === 'string';
}

if (isString(value)) {
    console.log(value.length);
} else {
    console.log(value.toFixed());
}

除了可以通过定义 类型保护函数 的方式来告诉编译器使用时联合类型的变量具体是什么类型以外,我们还可以使用 typeof 来实现 类型保护

注意点

  • 如果使用 typeof 来实现 类型保护, 那么只能使用 === / !==
  • 如果使用 typeof 来实现类型保护, 那么只能保护 number/string/boolean/symbol 类型

通过 typeof 实现类型保护:

let getRandomValue = (): (string | number) => {
    let num = Math.random();
    return (num >= 0.5) ? 'abc' : 123.123;
}

let value = getRandomValue();
console.log(value);

if (typeof value === 'string') {
    console.log(value.length);
} else {
    console.log(value.toFixed());
}

除了可以通过 typeof 类实现类型保护以外, 我们还可以通过 instanceof 来实现 类型保护

class Person {
    name: string = 'BNTang';
}

class Animal {
    age: number = 18;
}

let getRandomObject = (): (Person | Animal) => {
    let num = Math.random();
    return (num >= 0.5) ? new Person() : new Animal();
};

let obj = getRandomObject();
console.log(obj);

if (obj instanceof Person) {
    console.log(obj.name);
} else {
    console.log(obj.age);
}