TypeScript基礎講解

類型

js類型

JavaScript 的類型分爲兩種:原始數據類型(Primitive data types)和對象類型(Object types)。

原始數據類型包括:布爾值、數值、字符串、nullundefined 以及 ES6 中的新類型 Symbol

在JavaScript中undefined,是全局作用於的一個屬性,他會賦值給哪些聲明但未初始化的變量;

null是一個字面量(不是全局對象的一個屬性),他可以賦值給哪些沒有值得變量;

ts類型

在TypeScript中我們可以使用undefined和null來定義兩個原始類型數據:

let test: null = null;
console.log(test); //null
let test1: undefined = undefined;
console.log(test1); //undefined

undefinednull 是所有類型的子類型。也就是說 undefined 類型的變量,可以賦值給 所有類型的變量 如:

let u1: undefined;
let num1: number = u1;
console.log(num1); //undefined

void 類型的變量不能賦值給 number 類型的變量:

let u: void;
let num: number = u; //Type 'void' is not assignable to type 'number'.

數組類型

在 TypeScript 中,數組類型有多種定義方式,比較靈活。

最簡單的方法是使用「類型 + 方括號」來表示數組:

數組的項中不允許出現其他類型;

//正確
let numArray: number[] = [1,2,3];
let strArray: string[] = ['1','2','3'];
//Type 'string' is not assignable to type 'number'.
let numArray: number[] = ['1',2,3];

也可以使用數組泛型(Array Generic) Array<elemType> 來表示數組:

let objArray: Array<object> = [{a:1},{b:2}];

任意值any

任意值(Any)用來表示允許賦值爲任意類型。

any的定義

如果是普通類型,在賦值過程中是不能改變類型的 如:

let myTest: string = 'test';
myTest = true; 
//Type 'true' is not assignable to type 'string'.

如果是any,允許被賦值爲任意類型

let myTest: any = 'test';
myTest = true;
console.log(myTest); //true

any的屬性

在任意值上訪問任何屬性都是允許的:

let anyThing: any = 'hello';
console.log(anyThing.myName)

在聲明變量聲明是未指定類型,那麼就會被識別成任意類型

類型推論

如果沒有明確的指定類型,那麼 TypeScript 會依照類型推論(Type Inference)的規則推斷出一個類型。如下:

let myType = 'one';
myType = 1;//Type '1' is not assignable to type 'string'.
等價於
let myType:string = 'one';
myType = 1;//Type '1' is not assignable to type 'string'.

TypeScript 會在沒有明確的指定類型的時候推測出一個類型,這就是類型推論。

如果定義時沒有賦值,不管之後有沒有賦值,都會被推斷成any類型

聯合類型

TypeScript允許聲明聯合類型。聯合類型類聲明那些可以存儲多種類型的變量

let myType: string | number;
myType = 'one'; //one
myType = 1;//1
myType = true;//Type 'true' is not assignable to type 'ReactText'.

聯合類型使用 | 分隔每個類型。

接口

接口基礎用法

在面嚮對象語言中,接口(Interfaces)是一個很重要的概念,它是對行爲的抽象,而具體如何行動需要由類(classes)去實現(implement)。

TypeScript 中的接口是一個非常靈活的概念,除了可用於[對類的一部分行爲進行抽象]()以外,也常用於對「對象的形狀(Shape)」進行描述。

定義一個變量myJson,類型時Person

interface Person {
    name:string;
    age: number;
}
//定義變量比接口少一些屬性
//Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.
let myJson: Person = {
    name: 'jerry'
}

//定義的變量屬性比接口多
//Type '{ name: string; age: number; other: string; }' is not assignable to type 'Person'.
  Object literal may only specify known properties, and 'other' does not exist in type 'Person'.
let myJson: Person = {
    name: 'jerry',
    age: 1,
    other: 'test'
}

可選屬性

接口裏面的屬性不全都是必需的,有些只是在某些條件下存在或者根本就不存在。

可選屬性在應用”option bags“模式時很常用,即給函數傳入的對象中只有部分屬性賦值了

interface Person {
    name:string;
    age?: number;
}
//正常運行
let myJson: Person = {
    name: 'jerry'
}

可選屬性的含義是該屬性可以不存在。

這時仍然不允許添加未定義的屬性。

任意屬性

interface Person {
    name:string;
    age: number;
    [params: string]: any
}
let myJson: Person = {
    name: 'jerry',
    age: 1,
    order: {
        test: 'test'
    }
}

用[params: string]定義了屬性取string類型的值;

注意:一旦定義了任意屬性,那麼之前定義的確定屬性和可選屬性都必須是他的子集;

//Property 'name' of type 'string' is not assignable to string index type 'object'.
//Property 'age' of type 'number' is not assignable to string index type 'object'.
interface Person {
    name:string;
    age: number;
    [params: string]: object
}
let myJson: Person = {
    name: 'jerry',
    age: 1,
    order: {
        test: 'test'
    }
}

只讀屬性

有時候我們希望對象中的一些字段只能在創建的時候被賦值,那麼可以用 readonly 定義只讀屬性:

interface Person {
    readonly id: number;
    name:string;
    age: number;
    [params: string]: any
}
let myJson: Person = {
    id: 123,
    name: 'jerry',
    age: 1,
    order: {
        test: 'test'
    }
}
//Cannot assign to 'id' because it is a read-only property.
myJson.id = 345;

readonly和const

最簡單判斷該用readonly還是const的方法是看要把它做爲變量使用還是做爲一個屬性。 做爲變量使用的話用const,若做爲屬性則使用readonly

函數類型

在 JavaScript 中,有兩種常見的定義函數的方式——函數聲明(Function Declaration)和函數表達式(Function Expression)

用接口定義函數的形狀

使用接口的方式來定義一個函數需要符合的形狀:

interface SearchFunc {
    (source: string, subStr: string): boolean;
}
let mySearch: SearchFunc = (source:string, subStr:string) => {
    return source.search(subStr) !== -1;
}

有可選參數的函數

與JavaScript不同,調用函數時傳的參數的數量或者類型不符合函數中定義的參數要求是,TypeScript編譯器會報錯;如:

add = (foo:number,bar:number,foobar:number):number => {
    return foo+bar+foobar;
}
add(); //提供的參數不匹配函數的簽名
add(1,2);//提供的參數不匹配函數的簽名
add(1,2,3); 返回6

在一些場景下我們不需要傳所有的參數;TypeScript一個函數可選參數的特性;

在TypeScript中通過在函數參數後面追加一個?,指定參數是可選的

add = (foo:number,bar:number,foobar?:number):number => {
    return foo+bar+foobar;
}
add(); //提供的參數不匹配函數的簽名
add(1,2);返回3
add(1,2,3); 返回6

有默認參數的函數

當函數有可選參數時,我們必須檢測參數是否被傳遞了 如:

add = (foo:number,bar:number,foobar?:number):number => {
    return foo+bar+(foobar !== undefined ? foobar : 1 );
}

這樣來做並沒有錯,但是可以通過提供foobar的參數的默認值,來替代標記其爲可選參數,以改善可讀性

add = (foo:number,bar:number,foobar:number=1):number => {
    return foo+bar+foobar;
}

在聲明函數簽名時使用=提供一個默認值,即可指定函數參數是可選的;TypeScript編譯會在JavaScript輸出結果中生成一個if結構,在foobar參數沒有傳遞函數時設置一個默認值;

function add(foo, bar, foobar){
    if(foobar === void 0){
        foobar = 1;
    }
    return foo+bar+foobar;
}

void 0是TypeScript編譯器檢測一個變量是否爲undefined的用法;

有剩餘參數的函數

add = (foo:number,bar:number,foobar:number=1):number => {
    return foo+bar+foobar;
}

如果想調用add傳遞更多個參數該如何解決呢?

使用剩餘參數,剩餘參數語法允許把不限量的參數表示爲一個數組

add = (...foo:number[]):number => {
    let res = 0;
    for(let i=0; i < foo.length; i++){
        res += foo[i];
    }
    return res;
}
用...foo替換了參數foo、bar、foobar;一個剩餘參數必須包含一個數組類型,否則會出現編譯錯誤;
add(); //return 0
add(1); //return 1
add(1,2,3,4,5); //return 15
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章