好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

typescript中高级类型之交叉类型与联合类型

交叉类型

交叉类型的表示方法为 Type1 & Type2,结果是取这两个类型的并集。这里是官网的例子,做了注释:

 //   定义函数 extend,用来合并对象 
 function  extend<T, U>(first: T, second: U): T &  U {
      //   result 是要返回结果,类型断言为 T & U 
    let result = {} as T &  U

      //   遍历 first,结果存入 result 
     for (let id  in   first){
          //   不能将类型“T”分配给类型“T & U”,所以需使用断言 
        result[id] =  first[id] as any
    }

      //   遍历 second,结果存入 result 
     for (let id  in   second){
          if (! result.hasOwnProperty(id)){
              //   不能将类型“U”分配给类型“T & U”,同样需要断言 
            result[id] =  second[id] as any
        }
    }

      //   返回结果,类型是 T & U 
     return   result
}

  //   定义 Person 类,有 name 实例属性,类型为 string 
 class Person{
    constructor(public name: string){}
}

  //   定义接口,要求有 log() 函数 
 interface Loggable{
    log():   void  
}

  //   定义 ConsoleLogger 类,它实现了接口 Loggable,有实例方法 log() 
 class ConsoleLogger implements Loggable{
    log(){

    }
}

  //   使用 extend 方法合并两个类的实例,返回的是交叉类型,所以可以访问 name 和 log() 
let jim = extend( new  Person('Jim'),  new   ConsoleLogger())
let n  =  jim.name
jim.log() 

例子中的结果可以看到,交叉类型取的是并集,拥有两个类型成员的所有属性。

 

联合类型

联合类型的表示方法为 Type1 | Type2,结果是这两个类型中的一个。还是以官网例子做解释:

 function   PadLeft(value: string, padding: any){
      //   如果是 number 类型,则在 value 前填充对用空格 
     if ( typeof  padding === 'number' ){
          return  Array(padding + 1).join(' ') +  value
    }
      //   如果是 string 类型,则直接拼接 value 和 padding 
     if ( typeof  padding === 'string' ){
          return  padding +  value
    }

      //   如果不是 string 和 number,抛出错误 
     throw   new  Error(`Expected string or number, got '${padding}' .`)
}

PadLeft( "hello world", 4)  //   '    hello world' 

上述代码可以通过编译,能正常运行,但是有一个问题,就是 padding 的类型,当 padding 传入的既不是 number 也不是 string 时,虽然运行结果会抛出错误,但是在编译阶段不会提示问题:

padLeft("Hello world",  true );  //   编译阶段通过,运行时报错 

要在编译阶段就可以知道问题,可以使用联合类型来替代 any 类型:

 function  PadLeft(value: string, padding: string |  number){
      //   ... 
 }

PadLeft( "hello world",  true )  //   error,类型“true”的参数不能赋给类型“string | number”的参数。 

联合类型表示一个值可以是几种类型之一。 我们用竖线(  | )分隔每个类型,所以  number | string | boolean  表示一个值可以是  number ,  string ,或  boolean 。

 

需要注意的是,访问联合类型的属性时,只能访问此联合类型的所有类型里共有的属性:

let a: string |  number

a.length   //   类型“string | number”上不存在属性“length”。类型“number”上不存在属性“length”。 

length 不存在于 number,所以编译不通过。可以看出这跟交叉类型不一样,交叉类型是可以访问所有成员的属性。

 

总结

交叉类型是多个类型合并为一个类型,可以访问所有类型的属性;联合类型是多个类型中的某一个,只能访问所有类型的共有属性。

 

查看更多关于typescript中高级类型之交叉类型与联合类型的详细内容...

  阅读:48次