TypeScript --- 快速學習

1. typescript是什麼

  • Typescript是由微軟開發的一款開源的編程語言
  • Typescript是Javascript的超集,遵循最新的ES5/ES6規範。TypeScript擴展了Javascript語法
  • TypeScript更像後端Java、C#這樣的面嚮對象語言可讓JS開發大型企業應用
  • 愈來愈多的項目是基於TS的,好比VSCode、Angular六、Vue三、React16
  • TS提供的類型系統能夠幫助咱們在寫代碼的時候提供更豐富的語法提示
  • 在建立前的編譯階段通過類型系統的檢查,就能夠避免不少線上的錯誤

typescript

2. TypeScript安裝和編譯

2.1 安裝

cnpm i typescript -g
複製代碼
tsc helloworld.ts
複製代碼

2.2 Vscode+TypeScript

2.2.1 生成配置文件

tsc --init
複製代碼
{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 指定ECMAScript的目標版本*/
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 指定模塊代碼的生成方式*/
    // "lib": [],                             /* Specify library files to be included in the compilation. 指定編譯的時候用來包含的編譯文件*/
    // "allowJs": true,                       /* Allow javascript files to be compiled. 容許編譯JS文件*/
    // "checkJs": true,                       /* Report errors in .js files. 在JS中包括錯誤*/
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. 指定JSX代碼的生成方式 是保留仍是react-native或者react*/
    // "declaration": true,                   /* Generates corresponding '.d.ts' file.生成相應的類型聲明文件 */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. 爲每一個類型聲明文件生成相應的sourcemap*/
    // "sourceMap": true,                     /* Generates corresponding '.map' file. 生成對應的map文件 */
    // "outFile": "./",                       /* Concatenate and emit output to single file. 合併而且把編譯後的內容輸出 到一個文件裏*/
    // "outDir": "./",                        /* Redirect output structure to the directory.按原始結構輸出到目標目錄 */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. 指定輸入文件的根目錄,用--outDir來控制輸出的目錄結構*/
    // "composite": true,                     /* Enable project compilation 啓用項目編譯*/
    // "removeComments": true,                /* Do not emit comments to output. 移除註釋*/
    // "noEmit": true,                        /* Do not emit outputs. 不要輸出*/
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 當目標是ES5或ES3的時候提供對for-of、擴展運算符和解構賦值中對於迭代器的完整支持*/
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule').r把每個文件轉譯成一個單獨的模塊 */

    /* Strict Type-Checking Options */
    //"strict": true,                           /* Enable all strict type-checking options. 啓用徹底的嚴格類型檢查 */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. 不能使用隱式的any類型*/
    // "strictNullChecks": true,              /* Enable strict null checks. 啓用嚴格的NULL檢查*/
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. 啓用嚴格的函數類型檢查*/
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions.啓用函數上嚴格的bind call 和apply方法 */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. 啓用類上初始化屬性檢查*/
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type.在默認的any中調用 this表達式報錯 */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. 在嚴格模式下解析而且向每一個源文件中發射use strict*/

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. 有未使用到的本地變量時報錯 */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. 有未使用到的參數時報錯*/
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. 當不是全部的代碼路徑都有返回值的時候報錯*/
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. 在switch表達式中沒有替代的case會報錯 */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 指定模塊的解析策略 node classic*/
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. 在解析非絕對路徑模塊名的時候的基準路徑*/
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. 一些路徑的集合*/
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. 根目錄的列表,在運行時用來合併內容*/
    // "typeRoots": [],                       /* List of folders to include type definitions from. 用來包含類型聲明的文件夾列表*/
    // "types": [],                           /* Type declaration files to be included in compilation.在編譯的時候被包含的類型聲明 */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking.當沒有默認導出的時候容許默認導入,這個在代碼執行的時候沒有做用,只是在類型檢查的時候生效 */
    //"esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.*/
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks.不要symlinks解析的真正路徑 */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. 指定ts文件位置*/
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. 指定 map文件存放的位置 */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. 源文件和sourcemap 文件在同一文件中,而不是把map文件放在一個單獨的文件裏*/
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. 源文件和sourcemap 文件在同一文件中*/

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. 啓動裝飾器*/
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  }
}
複製代碼

2.2.2 執行編譯

tsc 
複製代碼

2.2.3 vscode運行

  • Terminal->Run Task-> tsc:build 編譯
  • Terminal->Run Task-> tsc:watch 編譯並監聽

2.2.4 npm scripts

  • npm run 其實是調用本地的 Shell 來執行對應的 script value,因此理論上能兼容全部 bash 命令
  • Shell 在類 Unix 系統上是 /bin/sh,在 Windows 上是 cmd.exe

2.2.5 npm scripts 的 PATH

  • npm run 會預置 PATH,對應包下的 node_modules/.bin 目錄

3. 數據類型

3.1 布爾類型(boolean)

let married: boolean=false;
複製代碼

3.2 數字類型(number)

let age: number=10;
複製代碼

3.3 字符串類型(string)

let firstname: string='zfpx';
複製代碼

3.4 數組類型(array)

let arr2: number[]=[4,5,6];
let arr3: Array<number>=[7,8,9];
複製代碼

3.5 元組類型(tuple)

  • 在 TypeScript 的基礎類型中,元組( Tuple )表示一個已知數量類型的數組
let zhufeng:[string,number] = ['zhufeng',5];
zhufeng[0].length;
zhufeng[1].toFixed(2);
複製代碼
元組 數組
每一項能夠是不一樣的類型 每一項都是同一種類型
有預約義的長度 沒有長度限制
用於表示一個固定的結構 用於表示一個列表
const animal:[string,number,boolean] = ['zhufeng',10,true];
複製代碼

3.6 枚舉類型(enum)

  • 事先考慮某一個變量的全部的可能的值,儘可能用天然語言中的單詞表示它的每個值
  • 好比性別、月份、星期、顏色、單位、學歷

3.6.1 普通枚舉

enum Gender{
    GIRL,
    BOY
}
console.log(`李雷是${Gender.BOY}`);
console.log(`韓梅梅是${Gender.GIRL}`);

enum Week{
    MONDAY=1,
    TUESDAY=2
}
console.log(`今天是星期${Week.MONDAY}`);
複製代碼

3.6.2 常數枚舉

  • 常數枚舉與普通枚舉的區別是,它會在編譯階段被刪除,而且不能包含計算成員。
  • 假如包含了計算成員,則會在編譯階段報錯
const enum Colors {
    Red,
    Yellow,
    Blue
}

let myColors = [Colors.Red, Colors.Yellow, Colors.Blue];
複製代碼
const enum Color {Red, Yellow, Blue = "blue".length};
複製代碼

3.7 任意類型(any)

  • any就是能夠賦值給任意類型
  • 第三方庫沒有提供類型文件時可使用any
  • 類型轉換遇到困難時
  • 數據結構太複雜難以定義
let root:any=document.getElementById('root');
root.style.color='red';
複製代碼
let root:(HTMLElement|null)=document.getElementById('root');
root!.style.color='red';//非空斷言操做符
複製代碼

3.8 null 和 undefined

  • null 和 undefined 是其它類型的子類型,能夠賦值給其它類型,如數字類型,此時,賦值後的類型會變成 null 或 undefined
  • strictNullChecks 參數用於新的嚴格空檢查模式,在嚴格空檢查模式下, null 和 undefined 值都不屬於任何一個類型,它們只能賦值給本身這種類型或者 any
let x: number;
x = 1;
x = undefined;    
x = null;   

let y: number | null | undefined;
y = 1;
y = undefined;   
y = null;   
複製代碼

3.9 void 類型

  • void 表示沒有任何類型
  • 當一個函數沒有返回值時,TS 會認爲它的返回值是 void 類型。
function greeting(name:string):void {
    console.log('hello',name);
    //當咱們聲明一個變量類型是 void 的時候,它的非嚴格模式(strictNullChecks:false)下僅能夠被賦值爲 null 和 undefined
    //嚴格模式(strictNullChecks:true)下只能返回undefined
    //return null;
    //return undefined;
}
複製代碼

3.10 never類型

never是其它類型(null undefined)的子類型,表明不會出現的值javascript

3.10.1

  • 做爲不會返回( return )的函數的返回值類型
// 返回never的函數 必須存在 沒法達到( unreachable ) 的終點
function error(message: string): never {
    throw new Error(message);
}
let result1 = error('hello');
// 由類型推論獲得返回值爲 never
function fail() {
    return error("Something failed");
}
let result = fail();

// 返回never的函數 必須存在 沒法達到( unreachable ) 的終點
function infiniteLoop(): never {
    while (true) {}
}
複製代碼

3.10.2 strictNullChecks

  • 在 TS 中, null 和 undefined 是任何類型的有效值,因此沒法正確地檢測它們是否被錯誤地使用。因而 TS 引入了 --strictNullChecks 這一種檢查模式
  • 因爲引入了 --strictNullChecks ,在這一模式下,null 和 undefined 能被檢測到。因此 TS 須要一種新的底部類型( bottom type )。因此就引入了 never。
// Compiled with --strictNullChecks
function fn(x: number | string) {
  if (typeof x === 'number') {
    // x: number 類型
  } else if (typeof x === 'string') {
    // x: string 類型
  } else {
    // x: never 類型
    // --strictNullChecks 模式下,這裏的代碼將不會被執行,x 沒法被觀察
  }
}
複製代碼

3.10.3 never 和 void 的區別

  • void 能夠被賦值爲 null 和 undefined的類型。 never 則是一個不包含值的類型。
  • 擁有 void 返回值類型的函數能正常運行。擁有 never 返回值類型的函數沒法正常返回,沒法終止,或會拋出異常。

3.11 類型推論

  • 是指編程語言中可以自動推導出值的類型的能力,它是一些強靜態類型語言中出現的特性
  • 定義時未賦值就會推論成any類型
  • 若是定義的時候就賦值就能利用到類型推論
let username2;
username2 = 10;
username2 = 'zhufeng';
username2 = null;
複製代碼

3.12 包裝對象(Wrapper Object)

  • JavaScript 的類型分爲兩種:原始數據類型(Primitive data types)和對象類型(Object types)。
  • 全部的原始數據類型都沒有屬性(property)
  • 原始數據類型
    • 布爾值
    • 數值
    • 字符串
    • null
    • undefined
    • Symbol
let name = 'zhufeng';
console.log(name.toUpperCase());

console.log((new String('zhufeng')).toUpperCase());
複製代碼
  • 當調用基本數據類型方法的時候,JavaScript 會在原始數據類型和對象類型之間作一個迅速的強制性切換
let isOK: boolean = true; // 編譯經過
let isOK: boolean = Boolean(1) // 編譯經過
let isOK: boolean = new Boolean(1); // 編譯失敗   指望的 isOK 是一個原始數據類型
複製代碼

3.13 聯合類型

  • 聯合類型(Union Types)表示取值能夠爲多種類型中的一種
  • 未賦值時聯合類型上只能訪問兩個類型共有的屬性和方法
let name: string | number;
console.log(name.toString());
name = 3;
console.log(name.toFixed(2));
name = 'zhufeng';
console.log(name.length);

export {};
複製代碼

3.14 類型斷言

  • 類型斷言能夠將一個聯合類型的變量,指定爲一個更加具體的類型
  • 不能將聯合類型斷言爲不存在的類型
let name: string | number;
console.log((name as string).length);
console.log((name as number).toFixed(2));
console.log((name as boolean));
複製代碼

3.15 字面量類型

  • 能夠把字符串、數字、布爾值字面量組成一個聯合類型
type ZType = 1 | 'One'|true;
let t1:ZType = 1;
let t2:ZType = 'One';
let t3:ZType = true;
複製代碼

3.16 字符串字面量 vs 聯合類型

  • 字符串字面量類型用來約束取值只能是某幾個字符串中的一個, 聯合類型(Union Types)表示取值能夠爲多種類型中的一種
  • 字符串字面量 限定了使用該字面量的地方僅接受特定的值,聯合類型 對於值並無限定,僅僅限定值的類型須要保持一致

4. 函數

4.1 函數的定義

  • 能夠指定參數的類型和返回值的類型
function hello(name:string):void {
    console.log('hello',name);
}
hello('zfpx');
複製代碼

4.2 函數表達式

  • 定義函數類型
type GetUsernameFunction = (x:string,y:string)=>string;
let getUsername:GetUsernameFunction = function(firstName,lastName){
  return firstName + lastName;
}
複製代碼

4.3 沒有返回值

let hello2 = function (name:string):void {
    console.log('hello2',name);
    return undefined;
}
hello2('zfpx');
複製代碼

4.4 可選參數

在TS中函數的形參和實參必須同樣,不同就要配置可選參數,並且必須是最後一個參數前端

function print(name:string,age?:number):void {
    console.log(name,age);
}
print('zfpx');
複製代碼

4.5 默認參數

function ajax(url:string,method:string='GET') {
    console.log(url,method);
}
ajax('/users');
複製代碼

4.6 剩餘參數

function sum(...numbers:number[]) {
    return numbers.reduce((val,item)=>val+=item,0);
}
console.log(sum(1,2,3));
複製代碼

4.7 函數重載

  • 在Java中的重載,指的是兩個或者兩個以上的同名函數,參數不同
  • 在TypeScript中,表現爲給同一個函數提供多個函數類型定義
let obj: any={};
function attr(val: string): void;
function attr(val: number): void;
function attr(val:any):void {
    if (typeof val === 'string') {
        obj.name=val;
    } else {
        obj.age=val;
    }
}
attr('zfpx');
attr(9);
attr(true);
console.log(obj);
複製代碼

5. 類

5.1 如何定義類

  • "strictPropertyInitialization": true /
    啓用類屬性初始化的嚴格檢查
    /
  • name!:string
class Person{
    name:string;
    getName():void{
        console.log(this.name);
    }
}
let p1 = new Person();
p1.name = 'zhufeng';
p1.getName();
複製代碼

5.2 存取器

  • 在 TypeScript 中,咱們能夠經過存取器來改變一個類中屬性的讀取和賦值行爲
  • 構造函數
    • 主要用於初始化類的成員變量屬性
    • 類的對象建立時自動調用執行
    • 沒有返回值
class User {
    myname:string;
    constructor(myname: string) {
        this.myname = myname;
    }
    get name() {
        return this.myname;
    }
    set name(value) {
        this.myname = value;
    }
}

let user = new User('zhufeng');
user.name = 'jiagou'; 
console.log(user.name); 
複製代碼
"use strict";
var User = /** @class */ (function () {
    function User(myname) {
        this.myname = myname;
    }
    Object.defineProperty(User.prototype, "name", {
        get: function () {
            return this.myname;
        },
        set: function (value) {
            this.myname = value;
        },
        enumerable: true,
        configurable: true
    });
    return User;
}());
var user = new User('zhufeng');
user.name = 'jiagou';
console.log(user.name);
複製代碼

5.3 參數屬性

class User {
    constructor(public myname: string) {}
    get name() {
        return this.myname;
    }
    set name(value) {
        this.myname = value;
    }
}

let user = new User('zhufeng');
console.log(user.name); 
user.name = 'jiagou'; 
console.log(user.name);
複製代碼

5.4 readonly

  • readonly修飾的變量只能在構造函數中初始化
  • 在 TypeScript 中,const 是常量標誌符,其值不能被從新分配
  • TypeScript 的類型系統一樣也容許將 interface、type、 class 上的屬性標識爲 readonly
  • readonly 實際上只是在編譯階段進行代碼檢查。而 const 則會在運行時檢查(在支持 const 語法的 JavaScript 運行時環境中)
class Animal {
    public readonly name: string
    constructor(name:string) {
        this.name = name;
    }
    changeName(name:string){
        this.name = name;
    }
}

let a = new Animal('zhufeng');
a.changeName('jiagou');
複製代碼

5.5 繼承

  • 子類繼承父類後子類的實例就擁有了父類中的屬性和方法,能夠加強代碼的可複用性
  • 將子類公用的方法抽象出來放在父類中,本身的特殊邏輯放在子類中重寫父類的邏輯
  • super能夠調用父類上的方法和屬性
class Person {
    name: string;//定義實例的屬性,默認省略public修飾符
    age: number;
    constructor(name:string,age:number) {//構造函數
        this.name=name;
        this.age=age;
    }
    getName():string {
        return this.name;
    }
    setName(name:string): void{
        this.name=name;
    }
}
class Student extends Person{
    no: number;
    constructor(name:string,age:number,no:number) {
        super(name,age);
        this.no=no;
    }
    getNo():number {
        return this.no;
    }
}
let s1=new Student('zfpx',10,1);
console.log(s1);

複製代碼

5.6 類裏面的修飾符

class Father {
    public name: string;  //類裏面 子類 其它任何地方外邊均可以訪問
    protected age: number; //類裏面 子類 均可以訪問,其它任何地方不能訪問
    private money: number; //類裏面能夠訪問, 子類和其它任何地方都不能夠訪問
    constructor(name:string,age:number,money:number) {//構造函數
        this.name=name;
        this.age=age;
        this.money=money;
    }
    getName():string {
        return this.name;
    }
    setName(name:string): void{
        this.name=name;
    }
}
class Child extends Father{
    constructor(name:string,age:number,money:number) {
        super(name,age,money);
    }
    desc() {
        console.log(`${this.name} ${this.age} ${this.money}`);
    }
}

let child = new Child('zfpx',10,1000);
console.log(child.name);
console.log(child.age);
console.log(child.money);
複製代碼

5.7 靜態屬性 靜態方法

class Father {
    static className='Father';
    static getClassName() {
        return Father.className;
    }
    public name: string;
    constructor(name:string) {//構造函數
        this.name=name;
    }

}
console.log(Father.className);
console.log(Father.getClassName());
複製代碼

5.8 抽象類

  • 抽象描述一種抽象的概念,沒法被實例化,只能被繼承
  • 沒法建立抽象類的實例
  • 抽象方法不能在抽象類中實現,只能在抽象類的具體子類中實現,並且必須實現
abstract class Animal {
    name!:string;
    abstract speak():void;
}
class Cat extends Animal{
    speak(){
        console.log('喵喵喵');
    }
}
let animal = new Animal();//Cannot create an instance of an abstract class
animal.speak();
let cat = new Cat();
cat.speak();
複製代碼
訪問控制修飾符 private protected public
只讀屬性 readonly
靜態屬性 static
抽象類、抽象方法 abstract

5.9 抽象類 vs 接口

  • 不一樣類之間公有的屬性或方法,能夠抽象成一個接口(Interfaces)
  • 而抽象類是供其餘類繼承的基類,抽象類不容許被實例化。抽象類中的抽象方法必須在子類中被實現
  • 抽象類本質是一個沒法被實例化的類,其中可以實現方法和初始化屬性,而接口僅可以用於描述,既不提供方法的實現,也不爲屬性進行初始化
  • 一個類能夠繼承一個類或抽象類,但能夠實現(implements)多個接口
  • 抽象類也能夠實現接口
abstract class Animal{
    name:string;
    constructor(name:string){
      this.name = name;
    }
    abstract speak():void;
  }
  interface Flying{
      fly():void
  }
class Duck extends Animal implements Flying{
      speak(){
          console.log('汪汪汪');
      }
      fly(){
          console.log('我會飛');
      }
}
let duck = new Duck('zhufeng');
duck.speak();
duck.fly();
複製代碼

5.10 抽象方法

  • 抽象類和方法不包含具體實現,必須在子類中實現
  • 抽象方法只能出如今抽象類中
  • 子類能夠對抽象類進行不一樣的實現
abstract class Animal{
    abstract speak():void;
}
class Dog extends  Animal{
    speak(){
        console.log('小狗汪汪汪');
    }
}
class Cat extends  Animal{
    speak(){
        console.log('小貓喵喵喵');
    }
}
let dog=new Dog();
let cat=new Cat();
dog.speak();
cat.speak();
複製代碼

5.11 重寫(override) vs 重載(overload)

  • 重寫是指子類重寫繼承自父類中的方法
  • 重載是指爲同一個函數提供多個類型定義
class Animal{
    speak(word:string):string{
        return '動做叫:'+word;
    }
}
class Cat extends Animal{
    speak(word:string):string{
        return '貓叫:'+word;
    }
}
let cat = new Cat();
console.log(cat.speak('hello'));
//--------------------------------------------
function double(val:number):number
function double(val:string):string
function double(val:any):any{
  if(typeof val == 'number'){
    return val *2;
  }
  return val + val;
}

let r = double(1);
console.log(r);
複製代碼

5.12 繼承 vs 多態

  • 繼承(Inheritance)子類繼承父類,子類除了擁有父類的全部特性外,還有一些更具體的特性
  • 多態(Polymorphism)由繼承而產生了相關的不一樣的類,對同一個方法能夠有不一樣的響應
class Animal{
    speak(word:string):string{
        return 'Animal: '+word;
    }
}
class Cat extends Animal{
    speak(word:string):string{
        return 'Cat:'+word;
    }
}
class Dog extends Animal{
    speak(word:string):string{
        return 'Dog:'+word;
    }
}
let cat = new Cat();
console.log(cat.speak('hello'));
let dog = new Dog();
console.log(dog.speak('hello'));
複製代碼

6. 接口

  • 接口一方面能夠在面向對象編程中表示爲行爲的抽象,另外能夠用來描述對象的形狀
  • 接口就是把一些類中共有的屬性和方法抽象出來,能夠用來約束實現此接口的類
  • 一個類能夠繼承另外一個類並實現多個接口
  • 接口像插件同樣是用來加強類的,而抽象類是具體類的抽象概念
  • 一個類能夠實現多個接口,一個接口也能夠被多個類實現,但一個類的能夠有多個子類,但只能有一個父類

6.1 接口

  • interface中能夠用分號或者逗號分割每一項,也能夠什麼都不加

6.1.1 對象的形狀

//接口能夠用來描述`對象的形狀`,少屬性或者多屬性都會報錯
interface Speakable{
    speak():void;
    name?:string;//?表示可選屬性
}

let speakman:Speakable = {
    speak(){},//少屬性會報錯
    name,
    age//多屬性也會報錯
}
複製代碼

6.1.2 行爲的抽象

//接口能夠在面向對象編程中表示爲行爲的抽象
interface Speakable{
    speak():void;
}
interface Eatable{
    eat():void
}
//一個類能夠實現多個接口
class Person implements Speakable,Eatable{
    speak(){
        console.log('Person說話');
    }
    eat(){}
}
class TangDuck implements Speakable{
    speak(){
        console.log('TangDuck說話');
    }
    eat(){}
}
複製代碼

6.1.3 任意屬性

//沒法預先知道有哪些新的屬性的時候,可使用 `[propName:string]:any`,propName名字是任意的
interface Person {
  readonly id: number;
  name: string;
  [propName: string]: any;
}

let p1 = {
  id:1,
  name:'zhufeng',
  age:10
}
複製代碼

6.2 接口的繼承

  • 一個接口能夠繼承自另一個接口
interface Speakable {
    speak(): void
}
interface SpeakChinese extends Speakable {
    speakChinese(): void
}
class Person implements SpeakChinese {
    speak() {
        console.log('Person')
    }
    speakChinese() {
        console.log('speakChinese')
    }
}
複製代碼

6.3 readonly

  • 用 readonly 定義只讀屬性能夠避免因爲多人協做或者項目較爲複雜等因素形成對象的值被重寫
interface Person{
  readonly id:number;
  name:string
}
let tom:Person = {
  id :1,
  name:'zhufeng'
}
tom.id = 1;
複製代碼

6.4 函數類型接口

  • 對方法傳入的參數和返回值進行約束
interface discount{
  (price:number):number
}
let cost:discount = function(price:number):number{
   return price * .8;
}
複製代碼

6.5 可索引接口

  • 對數組和對象進行約束
  • userInterface 表示:只要 index 的類型是 number,那麼值的類型必須是 string
  • UserInterface2 表示:只要 index 的類型是 string,那麼值的類型必須是 string
interface UserInterface {
  [index:number]:string
}
let arr:UserInterface = ['zfpx1','zfpx2'];
console.log(arr);

interface UserInterface2 {
  [index:string]:string
}
let obj:UserInterface2 = {name:'zhufeng'};

複製代碼

6.6 類接口

  • 對類的約束
interface Speakable {
    name: string;
    speak(words: string): void
}
class Dog implements Speakable {
    name!: string;
    speak(words:string) {
        console.log(words);
    }
}
let dog = new Dog();
dog.speak('汪汪汪');
複製代碼

6.7 構造函數的類型

  • 在 TypeScript 中,咱們能夠用 interface 來描述類
  • 同時也可使用interface裏特殊的new()關鍵字來描述類的構造函數類型
class Animal{
  constructor(public name:string){
  }
}
interface WithNameClass{
  new(name:string):Animal
}
function createAnimal(clazz:WithNameClass,name:string){
   return new clazz(name);
}
let a = createAnimal(Animal,'zhufeng');
console.log(a.name);
複製代碼

7. 泛型

  • 泛型(Generics)是指在定義函數、接口或類的時候,不預先指定具體的類型,而在使用的時候再指定類型的一種特性
  • 泛型T做用域只限於函數內部使用

7.1 泛型函數

  • 首先,咱們來實現一個函數 createArray,它能夠建立一個指定長度的數組,同時將每一項都填充一個默認值
function createArray(length: number, value: any): Array<any> {
  let result: any = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
let result = createArray(3,'x');
console.log(result);
複製代碼

使用了泛型java

function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
      result[i] = value;
    }
    return result;
  }
let result = createArray2<string>(3,'x');
console.log(result);
複製代碼

7.2 類數組

  • 類數組(Array-like Object)不是數組類型,好比 arguments
function sum(...parameters: number[]) {
    let args: IArguments = arguments;
    for (let i = 0; i < args.length; i++) {
        console.log(args[i]);
    }
}
sum(1, 2, 3);

let root = document.getElementById('root');
let children: HTMLCollection = (root as HTMLElement).children;
children.length;
let nodeList: NodeList = (root as HTMLElement).childNodes;
nodeList.length;
複製代碼

7.3 泛型類

class MyArray<T>{
    private list:T[]=[];
    add(value:T) {
        this.list.push(value);
    }
    getMax():T {
        let result=this.list[0];
        for (let i=0;i<this.list.length;i++){
            if (this.list[i]>result) {
                result=this.list[i];
            }
        }
        return result;
    }
}
let arr=new MyArray();
arr.add(1); arr.add(2); arr.add(3);
let ret = arr.getMax();
console.log(ret);
複製代碼

7.5 泛型接口

  • 泛型接口能夠用來約束函數
interface Calculate{
  <T>(a:T,b:T):T
}
let add:Calculate = function<T>(a:T,b:T){
  return a;
}
add<number>(1,2);

複製代碼

7.6 多個類型參數

  • 泛型能夠有多個
function swap<A,B>(tuple:[A,B]):[B,A]{
  return [tuple[1],tuple[0]];
}
let swapped = swap<string,number>(['a',1]);
console.log(swapped);
console.log(swapped[0].toFixed(2));
console.log(swapped[1].length);
複製代碼

7.7 默認泛型類型

function createArray3<T=number>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
let result2 = createArray3(3,'x');
console.log(result2);
複製代碼

7.8 泛型約束

  • 在函數中使用泛型的時候,因爲預先並不知道泛型的類型,因此不能隨意訪問相應類型的屬性或方法。
function logger<T>(val: T) {
    console.log(val.length); //直接訪問會報錯
}
//可讓泛型繼承一個接口
interface LengthWise {
    length: number
}
//可讓泛型繼承一個接口
function logger2<T extends LengthWise>(val: T) {
    console.log(val.length)
}
logger2('zhufeng');
logger2(1);
複製代碼

7.9 泛型接口

  • 定義接口的時候也能夠指定泛型
interface Cart<T>{
  list:T[]
}
let cart:Cart<{name:string,price:number}> = {
  list:[{name:'zhufeng',price:10}]
}
console.log(cart.list[0].name,cart.list[0].price);
複製代碼

7.10 泛型類型別名

  • 泛型類型別名能夠表達更復雜的類型
type Cart<T> = {list:T[]} | T[];
let c1:Cart<string> = {list:['1']};
let c2:Cart<number> = [1];
複製代碼

7.11 泛型接口 vs 泛型類型別名

  • 接口建立了一個新的名字,它能夠在其餘任意地方被調用。而類型別名並不建立新的名字,例如報錯信息就不會使用別名
  • 類型別名不能被 extends和 implements,這時咱們應該儘可能使用接口代替類型別名
  • 當咱們須要使用聯合類型或者元組類型的時候,類型別名會更合適

8.結構類型系統

8.1 接口的兼容性

  • 若是傳入的變量和聲明的類型不匹配,TS就會進行兼容性檢查
  • 原理是Duck-Check,就是說只要目標類型中聲明的屬性變量在源類型中都存在就是兼容的
interface Animal {
    name: string;
    age: number;
}

interface Person {
    name: string;
    age: number;
    gender: number
}
// 要判斷目標類型`Person`是否可以兼容輸入的源類型`Animal`
function getName(animal: Animal): string {
    return animal.name;
}

let p = {
    name: 'zhufeng',
    age: 10,
    gender: 0
}

getName(p);
//只有在傳參的時候兩個變量之間纔會進行兼容性的比較,賦值的時候並不會比較,會直接報錯
let a: Animal = {
    name: 'zhufeng',
    age: 10,
    gender: 0
}
複製代碼

8.2 基本類型的兼容性

//基本數據類型也有兼容性判斷
let num : string|number;
let str:string='zhufeng';
num = str;

//只要有toString()方法就能夠賦給字符串變量
let num2 : {
  toString():string
}

let str2:string='jiagour';
num2 = str2;
複製代碼

8.3 類的兼容性

  • 在TS中是結構類型系統,只會對比結構而不在乎類型
class Animal{
    name:string
}
class Bird extends Animal{
   swing:number
}

let a:Animal;
a = new Bird();

let b:Bird;
//並非父類兼容子類,子類不兼容父類
b = new Animal();
複製代碼
class Animal{
  name:string
}
//若是父類和子類結構同樣,也能夠的
class Bird extends Animal{}

let a:Animal;
a = new Bird();

let b:Bird;
b = new Animal();

複製代碼
//甚至沒有關係的兩個類的實例也是能夠的
class Animal{
  name:string
}
class Bird{
  name:string
}
let a:Animal ;
a = new Bird();
let b:Bird;
b = new Animal();
複製代碼

8.4 函數的兼容性

  • 比較函數的時候是要先比較函數的參數,再比較函數的返回值

8.4.1 比較參數

type sumFunc = (a:number,b:number)=>number;
let sum:sumFunc;
function f1(a:number,b:number):number{
  return a+b;
}
sum = f1;

//能夠省略一個參數
function f2(a:number):number{
   return a;
}
sum = f2;

//能夠省略二個參數
function f3():number{
    return 0;
}
sum = f3;

 //多一個參數可不行
function f4(a:number,b:number,c:number){
    return a+b+c;
}
sum = f4;
複製代碼

8.4.2 比較返回值

type GetPerson = ()=>{name:string,age:number};
let getPerson:GetPerson;
//返回值同樣能夠
function g1(){
    return {name:'zhufeng',age:10};
}
getPerson = g1;
//返回值多一個屬性也能夠
function g2(){
    return {name:'zhufeng',age:10,gender:'male'};
}
getPerson = g2;
//返回值少一個屬性可不行
function g3(){
    return {name:'zhufeng'};
}
getPerson = g3;
//由於有可能要調用返回值上的方法
getPerson().age.toFixed();
複製代碼

8.5 函數參數的協變

  • 目標若是可以兼容源就是能夠的
type LogFunc = (a:number|string)=>void;
let log:LogFunc;

function log1(a:number|string|boolean){
  console.log(a);
}
//目標若是可以兼容源就是能夠的
log = log1;
複製代碼

8.6 泛型的兼容性

  • 泛型在判斷兼容性的時候會先判斷具體的類型,而後再進行兼容性判斷
//接口內容爲空沒用到泛型的時候是能夠的
//1.接口內容爲空沒用到泛型的時候是能夠的
interface Empty<T>{}
let x!:Empty<string>;
let y!:Empty<number>;
x = y;

//2.接口內容不爲空的時候不能夠
interface NotEmpty<T>{
  data:T
}
let x1!:NotEmpty<string>;
let y1!:NotEmpty<number>;
x1 = y1;

//實現原理以下,稱判斷具體的類型再判斷兼容性
interface NotEmptyString{
    data:string
}

interface NotEmptyNumber{
    data:number
}
let xx2!:NotEmptyString;
let yy2!:NotEmptyNumber;
xx2 = yy2;
複製代碼

8.7 枚舉的兼容性

  • 枚舉類型與數字類型兼容,而且數字類型與枚舉類型兼容
  • 不一樣枚舉類型之間是不兼容的
//數字能夠賦給枚舉
enum Colors {Red,Yellow}
let c:Colors;
c = Colors.Red;
c = 1;
c = '1';

//枚舉值能夠賦給數字
let n:number;
n = 1;
n = Colors.Red;
複製代碼

9.類型保護

  • 類型保護就是一些表達式,他們在編譯的時候就能經過類型信息確保某個做用域內變量的類型
  • 類型保護就是可以經過關鍵字判斷出分支中的類型

9.1 typeof 類型保護

function double(input: string | number | boolean) {
    if (typeof input === 'string') {
        return input + input;
    } else {
        if (typeof input === 'number') {
            return input * 2;
        } else {
            return !input;
        }
    }
}
複製代碼

9.2 instanceof類型保護

class Animal {
    name!: string;
}
class Bird extends Animal {
    swing!: number
}
function getName(animal: Animal) {
    if (animal instanceof Bird) {
        console.log(animal.swing);
    } else {
        console.log(animal.name);
    }
}
複製代碼

9.3 null保護

  • 若是開啓了strictNullChecks選項,那麼對於可能爲null的變量不能調用它上面的方法和屬性
function getFirstLetter(s: string | null) {
    //第一種方式是加上null判斷
    if (s == null) {
        return '';
    }
    //第二種處理是增長一個或的處理
    s = s || '';
    return s.charAt(0);
}
//它並不能處理一些複雜的判斷,須要加非空斷言操做符
function getFirstLetter2(s: string | null) {
    function log() {
        console.log(s!.trim());
    }
    s = s || '';
    log();
    return s.charAt(0);
}
複製代碼

9.4 鏈判斷運算符

  • 鏈判斷運算符是一種先檢查屬性是否存在,再嘗試訪問該屬性的運算符,其符號爲 ?.
  • 若是運算符左側的操做數 ?. 計算爲 undefined 或 null,則表達式求值爲 undefined 。不然,正常觸發目標屬性訪問,方法或函數調用。
a?.b; //若是a是null/undefined,那麼返回undefined,不然返回a.b的值.
a == null ? undefined : a.b;

a?.[x]; //若是a是null/undefined,那麼返回undefined,不然返回a[x]的值
a == null ? undefined : a[x];

a?.b(); // 若是a是null/undefined,那麼返回undefined
a == null ? undefined : a.b(); //若是a.b不函數的話拋類型錯誤異常,不然計算a.b()的結果

a?.(); //若是a是null/undefined,那麼返回undefined
a == null ? undefined : a(); //若是A不是函數會拋出類型錯誤
//不然 調用a這個函數
複製代碼

鏈判斷運算符 還處於 stage1 階段,TS 也暫時不支持node

9.5 可辨識的聯合類型

  • 就是利用聯合類型中的共有字段進行類型保護的一種技巧
  • 相同字段的不一樣取值就是可辨識
interface WarningButton{
  class:'warning',
  text1:'修改'
}
interface DangerButton{
  class:'danger',
  text2:'刪除'
}
type Button = WarningButton|DangerButton;
function getButton(button:Button){
 if(button.class=='warning'){
  console.log(button.text1);
 }
 if(button.class=='danger'){
  console.log(button.text2);
 }
}
複製代碼

9.6 in操做符

  • in 運算符能夠被用於參數類型的判斷
interface Bird {
    swing: number;
}

interface Dog {
    leg: number;
}

function getNumber(x: Bird | Dog) {
    if ("swing" in x) {
      return x.swing;
    }
    return x.leg;
}
複製代碼

9.7 自定義的類型保護

  • TypeScript 裏的類型保護本質上就是一些表達式,它們會在運行時檢查類型信息,以確保在某個做用域裏的類型是符合預期的
  • 要自定義一個類型保護,只須要簡單地爲這個類型保護定義一個函數便可,這個函數的返回值是一個類型謂詞
  • 類型謂詞的語法爲 parameterName is Type 這種形式,其中 parameterName 必須是當前函數簽名裏的一個參數名`
interface Bird {
  swing: number;
}

interface Dog {
  leg: number;
}

//沒有相同字段能夠定義一個類型保護函數
function isBird(x:Bird|Dog): x is Bird{
  return (<Bird>x).swing == 2;
  return (x as Bird).swing == 2;
}
function getAnimal(x: Bird | Dog) {
  if (isBird(x)) {
    return x.swing;
  }
  return x.leg;
}
複製代碼

10. 類型變換

10.1 交叉類型

  • 交叉類型(Intersection Types)表示將多個類型合併爲一個類型
    interface Bird {
      name: string,
      fly(): void
    }
    interface Person {
      name: string,
      talk(): void
    }
    type BirdPerson = Bird & Person;
    let p: BirdPerson = { name: 'zhufeng', fly() { }, talk() { } };
    p.fly;
    p.name
    p.talk;
    複製代碼

10.2 typeof

  • 能夠獲取一個變量的類型
//先定義類型,再定義變量
type People = {
    name:string,
    age:number,
    gender:string
}
let p1:People = {
    name:'zhufeng',
    age:10,
    gender:'male'
}
複製代碼
//先定義變量,再定義類型
let p1 = {
    name:'zhufeng',
    age:10,
    gender:'male'
}
type People = typeof p1;
function getName(p:People):string{
    return p.name;
}
getName(p1);
複製代碼

10.3 索引訪問操做符

  • 能夠經過[]獲取一個類型的子類型
interface Person{
    name:string;
    age:number;
    job:{
        name:string
    };
    interests:{name:string,level:number}[]
}
let FrontEndJob:Person['job'] = {
    name:'前端工程師'
}
let interestLevel:Person['interests'][0]['level'] = 2;
複製代碼

10.4 keyof

  • 索引類型查詢操做符
interface Person{
  name:string;
  age:number;
  gender:'male'|'female';
}
//type PersonKey = 'name'|'age'|'gender';
type PersonKey = keyof Person;

function getValueByKey(p:Person,key:PersonKey){
  return p[key];
}
let val = getValueByKey({name:'zhufeng',age:10,gender:'male'},'name');
console.log(val);
複製代碼

10.5 映射類型

  • 在定義的時候用in操做符去批量定義類型中的屬性
interface Person{
  name:string;
  age:number;
  gender:'male'|'female';
}
//批量把一個接口中的屬性都變成可選的
type PartPerson = {
  [Key in keyof Person]?:Person[Key]
}

let p1:PartPerson={};
//也可使用泛型
type Part<T> = {
  [key in keyof T]?:T[key]
}
let p2:Part<Person>={};
複製代碼

10.6 內置工具類型

  • TS 中內置了一些工具類型來幫助咱們更好地使用類型系統

    10.6.1 Partial

  • Partial 能夠將傳入的屬性由非可選變爲可選,具體使用以下:
type Partial<T> = { [P in keyof T]?: T[P] };

interface A {
  a1: string;
  a2: number;
  a3: boolean;
}

type aPartial = Partial<A>;

const a: aPartial = {}; // 不會報錯
複製代碼

10.6.2 Required

  • Required 能夠將傳入的屬性中的可選項變爲必選項,這裏用了 -? 修飾符來實現。
//type Required<T> = { [P in keyof T]-?: T[P] };

interface Person{
  name:string;
  age:number;
  gender?:'male'|'female';
}
/**
 * type Require<T> = { [P in keyof T]-?: T[P] };
 */
let p:Required<Person> = {
  name:'zhufeng',
  age:10,
  //gender:'male'
}
複製代碼

10.6.3 Readonly

  • Readonly 經過爲傳入的屬性每一項都加上 readonly 修飾符來實現。
interface Person{
  name:string;
  age:number;
  gender?:'male'|'female';
}
//type Readonly<T> = { readonly [P in keyof T]: T[P] };
let p:Readonly<Person> = {
  name:'zhufeng',
  age:10,
  gender:'male'
}
p.age = 11;
複製代碼

10.6.4 Pick

  • Pick 可以幫助咱們從傳入的屬性中摘取某一項返回
interface Animal {
  name: string;
  age: number;
}
/**
 * From T pick a set of properties K
 * type Pick<T, K extends keyof T> = { [P in K]: T[P] };
 */
// 摘取 Animal 中的 name 屬性
type AnimalSub = Pick<Animal, "name">; //{ name: string; }
let a:AnimalSub = {
    name:'zhufeng',
    age:10
}
複製代碼

10.6.5 映射類型修飾符的控制

  • TypeScript中增長了對映射類型修飾符的控制
  • 具體而言,一個 readonly? 修飾符在一個映射類型裏能夠用前綴 +-來表示這個修飾符應該被添加或移除
  • TS 中部份內置工具類型就利用了這個特性(Partial、Required、Readonly...),這裏咱們能夠參考 Partial、Required 的實現

10.7 條件類型

  • 在定義泛型的時候可以添加進邏輯分支,之後泛型更加靈活

10.7.1 定義條件類型

interface Fish {
    name: string
}
interface Water {
    name: string
}
interface Bird {
    name: string
}
interface Sky {
    name: string
}
//三元運算符
type Condition<T> = T extends Fish ? Water : Sky;
let condition: Condition<Fish> = { name: '水' };
複製代碼

10.7.2 條件類型的分發

interface Fish {
    fish: string
}
interface Water {
    water: string
}
interface Bird {
    bird: string
}
interface Sky {
    sky: string
}

type Condition<T> = T extends Fish ? Water : Sky;
//(Fish extends Fish ? Water : Sky) | (Bird extends Fish ? Water : Sky)
// Water|Sky
let condition1: Condition<Fish | Bird> = { water: '水' };
let condition2: Condition<Fish | Bird> = { sky: '天空' };
複製代碼

10.7.3 內置條件類型

  • TS 在內置了一些經常使用的條件類型,能夠在 lib.es5.d.ts 中查看:
10.7.3.1 Exclude
  • 從 T 可分配給的類型中排除 U
    type  E = Exclude<string|number,string>;
    let e:E = 10;
    複製代碼
10.7.3.2 Extract
  • 從 T 可分配的類型中提取 U
    type  E = Extract<string|number,string>;
    let e:E = '1';
    複製代碼
10.7.3.3 NonNullable
  • 從 T 中排除 null 和 undefined
type  E = NonNullable<string|number|null|undefined>;
let e:E = null;
複製代碼
10.7.3.4 ReturnType
  • 獲取函數類型的返回類型 `js function getUserInfo() { return { name: "zhufeng", age: 10 }; }

// 經過 ReturnType 將 getUserInfo 的返回值類型賦給了 UserInfo type UserInfo = ReturnType;react

const userA: UserInfo = { name: "zhufeng", age: 10 };jquery

##### 10.7.3.5 InstanceType<T>
-  獲取構造函數類型的實例類型
```js
class Person{
  name:string;
  constructor(name){
    this.name = name;
  }
  getName(){console.log(this.name)}
}

type  P = InstanceType<typeof Person>;
let p:P = {name:'zhufeng',getName(){}};
複製代碼

11.類型聲明

  • 聲明文件可讓咱們不須要將JS重構爲TS,只須要加上聲明文件就可使用系統
  • 類型聲明在編譯的時候都會被刪除,不會影響真正的代碼

11.1 普通類型聲明

declare const $:(selector:string)=>{ //變量
    click():void;
    width(length:number):void;
};
declare let name:string;  //變量
declare let age:number;  //變量
declare function getName():string;  //方法
declare class Animal{name:string}  //類

interface Person{ //聲明接口
    name:string
}

type Student = { //聲明類型
    name:string
}|'string';
複製代碼

11.2 外部枚舉

  • 外部枚舉是使用declare enum定義的枚舉類型
  • 外部枚舉用來描述已經存在的枚舉類型的形狀
declare enum Seasons {
    Spring,
    Summer,
    Autumn,
    Winter
}

let seasons = [
    Seasons.Spring,
    Seasons.Summer,
    Seasons.Autumn,
    Seasons.Winter
];
複製代碼

declare 定義的類型只會用於編譯時的檢查,編譯結果中會被刪除。上例的編譯結果以下webpack

var seasons = [
    Seasons.Spring,
    Seasons.Summer,
    Seasons.Autumn,
    Seasons.Winter
];
複製代碼

也能夠同時使用declareconstgit

declare const enum Seasons {
    Spring,
    Summer,
    Autumn,
    Winter
}

let seasons = [
    Seasons.Spring,
    Seasons.Summer,
    Seasons.Autumn,
    Seasons.Winter
];
複製代碼

編譯結果github

var seasons = [
    0 /* Spring */,
    1 /* Summer */,
    2 /* Autumn */,
    3 /* Winter */
];
複製代碼

11.3 namespace

  • 若是一個全局變量包括了不少子屬性,可能使用namespace
  • 在聲明文件中的namespace表示一個全局變量包含不少子屬性
  • 在命名空間內部不須要使用 declare 聲明屬性或方法
declare namespace ${
    function ajax(url:string,settings:any):void;
    let name:string;
    namespace fn {
        function extend(object:any):void;
    }
}
$.ajax('/api/users',{});
$.fn.extend({
    log:function(message:any){
        console.log(message);
    }
});
export {};

複製代碼

11.4 類型聲明文件

  • 咱們能夠把類型聲明放在一個單獨的類型聲明文件中
  • 能夠在類型聲明文件中使用類型聲明
  • 文件命名規範爲*.d.ts
  • 觀看類型聲明文件有助於瞭解庫的使用方式

11.4.1 jquery.d.ts

typings\jquery.d.tsweb

declare const $:(selector:string)=>{
    click():void;
    width(length:number):void;
}
複製代碼

11.4.2 tsconfig.json

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "ES2015",  
    "outDir":"lib"
  },
  "include": [
    "src/**/*",
    "typings/**/*"
  ]
}
複製代碼

11.4.3 test.js

$('#button').click();
$('#button').width(100);
export {};
複製代碼

11.5 第三方聲明文件

  • 能夠安裝使用第三方的聲明文件
  • @types是一個約定的前綴,全部的第三方聲明的類型庫都會帶有這樣的前綴
  • JavaScript 中有不少內置對象,它們能夠在 TypeScript 中被當作聲明好了的類型
  • 內置對象是指根據標準在全局做用域(Global)上存在的對象。這裏的標準是指 ECMAScript 和其餘環境(好比 DOM)的標準
  • 這些內置對象的類型聲明文件,就包含在TypeScript 核心庫的類型聲明文件

11.5.1 使用jquery

//對於common.js風格的模塊必須使用 import * as 
import * as jQuery from 'jquery';
jQuery.ajax('/user/1');
複製代碼

11.5.2 安裝聲明文件

cnpm i @types/jquery -S
複製代碼

11.5.3 本身編寫聲明文件

types\jquery\index.d.ts

declare function jQuery(selector:string):HTMLElement;
declare namespace jQuery{
  function ajax(url:string):void
}
export default jQuery;
複製代碼

tsconfig.json

  • 若是配置了paths,那麼在引入包的的時候會自動去paths目錄裏找類型聲明文件
  • 在 webpack 中,咱們能夠經過配置 alias 的形式來爲項目裏的文件作映射。在 tsconfig.json 中,咱們一樣也能夠作路徑的映射
  • 在 tsconfig.json 中,咱們經過 compilerOptions 裏的 paths 屬性來配置路徑映射。 tsconfig.json
    {
    "baseUrl": "./",// 使用 paths 屬性的話必需要指定 baseUrl 的值
    "paths": {
    "*":["types/*"]
    }
    複製代碼

11.5.4 npm聲明文件可能的位置

  • node_modules/jquery/package.json
    • "types":"types/xxx.d.ts"
  • node_modules/jquery/index.d.ts
  • node_modules/@types/jquery/index.d.ts

11.6 擴展全局變量的類型

11.6.1 擴展局部變量類型

interface String {
    double():string;
}

String.prototype.double = function(){
    return this+'+'+this;
}
console.log('hello'.double());

interface Window{
    myname:string
}
console.log(window.myname);
//export {}
複製代碼

11.6.2 模塊內全局擴展

types\global\index.d.ts

declare global{
    interface String {
        double():string;
    }
    interface Window{
        myname:string
    }
}

export  {}
複製代碼
"include": [
    "src/**/*",
    "types/**/*"
]
複製代碼

11.7 合併聲明

  • 同一名稱的兩個獨立聲明會被合併成一個單一聲明
  • 合併後的聲明擁有原先兩個聲明的特性
  • 類既能夠做爲類型使用,也能夠做爲值使用,接口只能做爲類型使用
關鍵字 做爲類型使用 做爲值使用
class yes yes
enum yes yes
interface yes no
type yes no
function no yes
var,let,const no yes
class Person{
    name:string=''
}
let p1:Person;//做爲類型使用
let p2 = new Person();//做爲值使用

interface Animal{
    name:string
}
let a1:Animal;
let a2 = Animal;//接口類型不能用做值
複製代碼

11.7.1 合併類型聲明

  • 能夠經過接口合併的特性給一個第三方爲擴展類型聲明

use.js

interface Animal{
    name:string
}
let a1:Animal={name:'zhufeng',age:10};
console.log(a1.name);
console.log(a1.age);
複製代碼

types\animal\index.d.ts

interface Animal{
    age:number
}
複製代碼

11.7.2 使用命名空間擴展類

  • 咱們可使用 namespace 來擴展類,用於表示內部類
    class Form {
      username: Form.Item='';
      password: Form.Item='';
    }
    //Item爲Form的內部類
    namespace Form {
      export class Item {}
    }
    let item:Form.Item = new Form.Item();
    console.log(item);
    複製代碼

11.7.3 使用命名空間擴展函數

  • 咱們也可使用 namespace 來擴展函數
function greeting(name: string): string {
    return greeting.words+name;
}

namespace greeting {
    export let words = "Hello,";
}

console.log(greeting('zhufeng'))
複製代碼

11.7.4 使用命名空間擴展枚舉類型

enum Color {
    red = 1,
    yellow = 2,
    blue = 3
}

namespace Color {
    export const green=4;
    export const purple=5;
}
console.log(Color.green)
複製代碼

11.8 生成聲明文件 #

  • 把TS編譯成JS後丟失類型聲明,咱們能夠在編譯的時候自動生成一份JS文件
{
  "compilerOptions": {
     "declaration": true, /* Generates corresponding '.d.ts' file.*/
  }
}複製代碼
相關文章
相關標籤/搜索