1. 交叉类型
      交叉类型是将多个类型合并为一个类型。可以把现有的多种类型叠加到为一种类型,包含了所有类型的特性。
      1. function extend<T, U>(first: T, second: U): T & U {
      2. let result = <T & U>{};
      3. for (let id in first) {
      4. (<any>result)[id] = (<any>first)[id];
      5. }
      6. for (let id in second) {
      7. if (!result.hasOwnProperty(id)) {
      8. (<any>result)[id] = (<any>second)[id];
      9. }
      10. }
      11. return result;
      12. }
    2. 联合类型
      联合类型和交叉类型很有关联,但是使用上却完全不同。访问共同拥有的 ```typescript interface a { fly(); layEggs(); }

    interface b { swim(); layEggs(); }

    function getSmallPet(): b | a { // … }

    let pet = getSmallPet(); pet.layEggs(); // okay pet.swim(); // errors

    1. 3. 类型保护和区别类型
    2. ```typescript
    3. let pet = getSmallPet();
    4. // 每一个成员访问都会报错
    5. if (pet.swim) {
    6. pet.swim();
    7. }
    8. else if (pet.fly) {
    9. pet.fly();
    10. }

    类型断言使上面代码执行

    1. let pet = getSmallPet();
    2. if ((pet as Fish).swim) {
    3. (<Fish>pet).swim();
    4. }
    5. else {
    6. (<Bird>pet).fly();
    7. }

    4.用户自定义的类型保护
    一旦检查过类型,之后的每个分支都清楚的知道类型。
    要定义一个类型保护,我们只要简单地定义一个函数,它的返回值是一个 类型谓词:
    pet is Fish就是类型谓词,谓词为 parameterName is Type这种形式, parameterName必须是来自于当前函数签名里的一个参数名。

    1. function isFish(pet: Fish | Bird): pet is Fish {
    2. return (<Fish>pet).swim !== undefined;
    3. }
    1. // 'swim' 和 'fly' 调用都没有问题了
    2. if (isFish(pet)) {
    3. pet.swim();
    4. }
    5. else {
    6. pet.fly();
    7. }

    typeof类型保护

    1. function isNumber(x: any): x is number {
    2. return typeof x === "number";
    3. }
    4. function isString(x: any): x is string {
    5. return typeof x === "string";
    6. }
    7. function padLeft(value: string, padding: string | number) {
    8. if (isNumber(padding)) {
    9. return Array(padding + 1).join(" ") + value;
    10. }
    11. if (isString(padding)) {
    12. return padding + value;
    13. }
    14. throw new Error(`Expected string or number, got '${padding}'.`);
    15. }

    不需要将typeof抽象成一个函数,ts可以识别它为一个类型保护,所以可以直接在代码里检查类型。

    1. function padLeft(value: string, padding: string | number) {
    2. if (typeof padding === "number") {
    3. return Array(padding + 1).join(" ") + value;
    4. }
    5. if (typeof padding === "string") {
    6. return padding + value;
    7. }
    8. throw new Error(`Expected string or number, got '${padding}'.`);
    9. }

    这些 typeof类型保护只有两种形式能被识别: typeof v === "typename"typeof v !== "typename""typename"必须是 "number""string""boolean""symbol"。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护