TypeScript 高级类型整理

一、交叉类型(Intersection Types)

交叉类型是奖多个类型合并为一个类型。这往我们可以把多个现有的多种类型叠加成为一种类型,它包含了所需的所有类型的特性。主要用于多个对象的混合。

例如, Person & Serializable & Loggable同时是PersonSerializableLoggable。 就是说这个类型的对象同时拥有了这三种类型的成员。

将多个对象混合成一个交叉类型,这种操作用的情况应该比较少

function extend(first: T, second: U): T & U {
    let result = {};
    for (let id in first) {
        (result)[id] = (first)[id];
    }
    for (let id in second) {
        if (!result.hasOwnProperty(id)) {
            (result)[id] = (second)[id];
        }
    }
    return result;
}
class Person {
    constructor(public name: string) { }
}
interface Loggable {
    log(): void;
}
class ConsoleLogger implements Loggable {
    log() {
        // ...
    }
}
var jim = extend(new Person("Jim"), new ConsoleLogger());
var n = jim.name;
jim.log();

二、联合类型(UnionTypes)

联合类型与交叉类型很有关联,但是使用上却完全不同。

联合类型,将类型使用 | 关联在一起。

联合类型,可以将一个变量指定为已知的默写类型,可以将函数的返回值指定为已知的默写类型。

当前一个函数需要传入string类型或者number类型,可以使用any,同样更推荐使用联合类型。

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

let indentedString = padLeft("Hello world", true); // errors during compilation
返回类型中,使用联合类型

interface Bird {
    fly();
    layEggs();
}

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

function getSmallPet(): Fish | Bird {
    // ...
}

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

对于类型的私有部分

let pet=getSmallPet();
pet.layEggs();
//对于两种类型的个字的特有的方法,编译异常
// pet.fly();
// pet.swim();
1.类型保护与区分类型,使用类型断言处理<>或者as

//使用类型断言,判断类型的理由部分
//使用类型断言,编写代码的时候有代码提示
if((pet).fly){
    (pet as Bird).fly();
}else{
    (pet).swim();
}

2.用户自定义类型区分,使用 is 谓词

类型判断方法

function isFish(pet: Fish | Bird): pet is Fish {
    return (pet).swim !== undefined;
}
 谓词为  parameterName is Type 这种形式, parameterName 必须是来自于当前函数签名里的一个参数名。
3.typeof 类型保护,主要用于判断基础类型

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

function padLeft(value: string, padding: string | number) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}
4.instanceof 类型保护

instanceof类型保护是通过构造函数来细化类型的一种方式。
1.instanceof要求判断类型有构造函数,也就是对类类型可判断,如果是接口类型则不能使用

2.编译器会识别instanceof,在编写代码识别的时候,会有自动提示

interface Padder {
    getPaddingString(): string;
}
class SpaceRepeatingPadder implements Padder {
    repeat: string = '张三丰';
    getPaddingString() {
        return 'space';
    }
}
class StringPadder implements Padder {
    age: number = 15,
    getPaddingString() {
        return 'string';
    }
}
function getRandomPadder(): Padder {
    return Math.random() < 0.5 ?
        new SpaceRepeatingPadder() :
        new StringPadder();
}
let padder: Padder = getRandomPadder();
//使用 instanceof 类型保护
//编译器自动识别,写代码时自动根据类型提示
if (padder instanceof SpaceRepeatingPadder) {
    console.log(padder.repeat);
}
if (padder instanceof StringPadder) {
    console.log(padder.age);
}
5.可以为null的类型,可选参数、可选属性

TypeScript具有两种特殊的类型,nullundefined,它们分别具有值null和undefined. 我们在基础类型一节里已经做过简要说明。 默认情况下,类型检查器认为 nullundefined可以赋值给任何类型。
--strictNullChecks标记可以解决此错误:当你声明一个变量时,它不会自动地包含nullundefined

默认情况下这个属性不启用。

 你可以使用联合类型明确的包含它们:

let s = "foo";
s = null; // 错误, 'null'不能赋值给'string'
let sn: string | null = "bar";
sn = null; // 可以

sn = undefined; // error, 'undefined'不能赋值给'string | null'
使用了 --strictNullChecks ,可选参数会被自动地加上 | undefined:

默认情况下这个属性是启用的。

function f(x: number, y?: number) {
    return x + (y || 0);
}
f(1, 2);
f(1);
f(1, undefined);
f(1, null); // error, 'null' is not assignable to 'number | undefined'

三、类型别名 type 

类型别名会给一个类型启一个新的名字。

器别名不会新建一个类型。

类型别名可以使用泛型。

不能被extendsimplements扩展。

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    }
    else {
        return n();
    }
}

四、字符串字面量类型

字符串字面量类型允许你指定字符串必须的固定值。在实际应用中,字符串字面量类型可以与联合类型,类型保护和类型别名很好的配合。

通过结合使用这些特性,你可以实现类似枚举类型的字符串

type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
    animate(dx: number, dy: number, easing: Easing) {
        if (easing === "ease-in") {
            // ...
        }
        else if (easing === "ease-out") {
        }
        else if (easing === "ease-in-out") {
        }
        else {
            // error! should not pass null or undefined.
        }
    }
}

let button = new UIElement();
button.animate(0, 0, "ease-in");
button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here

五、可辨识联合(Discriminated Unions)

感觉不太好用。

多态的this类型

多态的this类型表示的是某个包含类或接口的子类型。 这被称做 F-bounded多态性。 它能很容易的表现连贯接口间的继承,比如。 在计算器的例子里,在每个操作之后都返回 this类型:

class BasicCalculator {
    public constructor(protected value: number = 0) { }
    public currentValue(): number {
        return this.value;
    }
    public add(operand: number): this {
        this.value += operand;
        return this;
    }
    public multiply(operand: number): this {
        this.value *= operand;
        return this;
    }
    // ... other operations go here ...
}

let v = new BasicCalculator(2)
            .multiply(5)
            .add(1)
            .currentValue();

六、索引类型(Index Types)

暂时忽略

七、映射类型

暂时忽略


更多:

TypeScript 类型兼容性整理

TypeScript 类型推论整理

TypeScript 枚举使用整理

你可能感兴趣的:(TypeScript)