TS系列之高级类型

高级类型

交叉类型

将多个类型合并为一个类型。函数

function extend<T, U>(first: T, second: U): T & U {
    let result = <T & U>{};
    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();

联合类型

表示取值能够为多种类型中的一种。this

  • 联合类型使用 | 分隔每一个类型。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

若是一个值是联合类型,咱们只能访问此联合类型的全部类型里共有的成员。code

function getString(something: string | number): string {
    return something.toString();
}

混合类型

一个例子就是,一个对象能够同时作为函数和对象使用,并带有额外的属性。对象

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) { };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

类型断言

能够用来手动指定一个值的类型。
它没有运行时的影响,只是在编译阶段起做用。
类型断言有两种形式。ip

//<类型>值
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
//值 as 类型
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
//须要在还不肯定类型的时候就访问其中一个类型的属性或方法
function getLength(something: string | number): number {
    if (something.length) {
        return something.length;
    } else {
        return something.toString().length;
    }
}          //报错

//使用类型断
function getLength(something: string | number): number {
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

类型断言不是类型转换,断言成一个联合类型中不存在的类型是不容许的get

类型推论

TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论。编译器

let x = 3;
变量x的类型被推断为数字。 这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时。

若是定义的时候没有赋值,无论以后有没有赋值,都会被推断成 any 类型而彻底不被类型检查。string

类型兼容性

TypeScript里的类型兼容性是基于结构子类型的。 结构类型是一种只使用其成员来描述类型的方式。it

TypeScript结构化类型系统的基本规则是,若是x要兼容y,那么y至少具备与x相同的属性。io

interface Named {
    name: string;
}

let x: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: 'Alice', location: 'Seattle' };
x = y;

//检查函数参数时使用相同的规则
function greet(n: Named) {
    alert('Hello, ' + n.name);
}
greet(y); // OK

这里要检查y是否能赋值给x,编译器检查x中的每一个属性,看是否能在y中也找到对应属性。 在这个例子中, y必须包含名字是name的string类型成员。y知足条件,所以赋值正确。

函数

形参

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;

y = x; // OK
x = y; // Error
容许忽略参数。

返回值

let x = () => ({name: 'Alice'});
let y = () => ({name: 'Alice', location: 'Seattle'});

x = y; // OK
y = x; // Error because x() lacks a location proper

枚举

枚举类型与数字类型兼容,而且数字类型与枚举类型兼容。不一样枚举类型之间是不兼容的。

enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };

let status = Status.Ready;
status = Color.Green;  //error

比较两个类类型的对象时,只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内。

class Animal {
    feet: number;
    constructor(name: string, numFeet: number) { }
}

class Size {
    feet: number;
    constructor(numFeet: number) { }
}

let a: Animal;
let s: Size;

a = s;  //OK
s = a;  //OK
相关文章
相关标签/搜索