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
相關文章
相關標籤/搜索