TypeScript 能够在特定区块中保证变量属于某种确定的类型,可以在此区块中放心地引用此类型的属性或者调用此类型的方法。

解决的问题

  1. enum Type {
  2. Strong,
  3. Week
  4. }
  5. class Java {
  6. helloJava() {
  7. }
  8. }
  9. class JavaScript {
  10. helloJavaScript() {
  11. }
  12. }
  13. function getLanguage(type: Type) {
  14. let lang = type === Type.Strong ? new Java() : new JavaScript();
  15. // 下面这种判断形式经常用到
  16. if (lang.helloJava) { // 但是 TS 会报错,因为 TS 判断 lang 是一个联合类型,不一定具有 helloJava 方法,下面方法的调用也是一样的
  17. lang.helloJava();
  18. } else {
  19. lang.helloJavaScript();
  20. }
  21. return lang;
  22. }

解决上面问题的办法,可以使用类型断言:

if ((lang as Java).helloJava) {
  (lang as Java).helloJava();
} else {
  (lang as JavaScript).helloJavaScript();
}

但是这种办法显然非常的繁琐,此时我们就可以使用类型保护了。

触发类型保护

instanceof

使用这个关键字,可以触发类型保护:用于判断某个变量是不是某个类的实例

if (lang instanceof Java) {
  // 此时 TS 可以保证在这个区块中一定是 Java 类型
  lang.helloJava();
} else {
  // 这个区块也被直接保证为 JavaScript 类型
  lang.helloJavaScript();
}

in

使用这个关键字,可以触发类型保护:用于判断某个属性是不是属于某个对象

if ('helloJava' in lang) {
 // 此时 TS 可以保证在这个区块中一定是 Java 类型
  lang.helloJava();
} else {
  // 这个区块也被直接保证为 JavaScript 类型
  lang.helloJavaScript();
}

typeof

使用这个关键字,可以触发类型保护:用于判断某个变量的类型:

if (typeof x === 'string') {
    x.length;
} else {
    x.toFixed();
}

类型保护函数

通过创建一个函数来实现类型保护:

function isJava(lang: Java | JavaScript): lang is Java { // 注意返回值的类型
    return (lang as Java).helloJava !== undefined;
}

if (isJava(lang)) {
 // 此时 TS 可以保证在这个区块中一定是 Java 类型
  lang.helloJava();
} else {
  // 这个区块也被直接保证为 JavaScript 类型
  lang.helloJavaScript();
}