【基礎知識】TypeScript學習

與JS相似部分,本文不作說明(運算符、條件語句、循環語句、函數、基本類型等)javascript

前言

  • TypeScript的設計目的應該是解決JavaScript的痛點弱類型沒有命名空間,致使很難模塊化,不適合開發大型程序。另外它還提供了一些語法糖來幫助你們更方便地實踐面向對象的編程。前端

  • TypeScript並無拋棄JavaScript的語法另起爐竈,而是作成了JavaScript的超集,這樣任何合法的JavaScript的語句在TypeScript下都是合法的,也就是說學習成本很低java

  • 語法糖:TypeScript能夠實現類,接口,枚舉,泛型,方法重載等,用簡潔的語法豐富了JavaScript的使用。node

  • 類型檢查:谷歌的Flow也能夠作到ajax

  • ES6用類Class(語法糖)也挺好用的啦......typescript

因此爲啥要用TypeScript

  1. TypeScript開發實戰
  2. 從移動終端到後端服務,從 IoT 到神經網絡,JavaScript 幾乎無處不在。如此廣闊的應用領域,天然對語言的安全性、健壯性和可維護性有更高的要求。
  3. 儘管 ES 標準在近幾年有了長足的進步,但在類型檢查方面依然無所建樹。你們可能經常會遇到這樣到場景:
  4. 你調用一個別人寫的函數,很不幸,這個傢伙沒有留下任何註釋,爲了搞清楚參數類型,你只能硬着頭皮去看裏面的邏輯。
  5. 爲了保證代碼的健壯性,你頗有責任心,對一個函數的輸入參數進行各類假設,最終給老闆盛上了一碗香噴噴的意大利麪。
  6. 領導看好你,讓你維護一個重要的底層類庫,你殫精竭慮,優化了一個參數類型,但不知道有多少處引用,在提交代碼前,是否感到脊背發涼?
  7. 明明定義好了接口,可一聯調就報錯了——「TypeError: Cannot read property 'length' of undefined」,因而你怒氣衝衝地去找後端理論:「嘿,哥們兒!這個字段是數組!這個字段是數組!這個字段是數組!」
  8. 歸根結底,是由於 JavaScript 是一門動態弱類型語言, 對變量的類型很是寬容,並且不會在這些變量和它們的調用者之間創建結構化的契約。若是你長期在沒有類型約束的環境下開發,就會形成「類型思惟」的缺失,養成不良的編程習慣,這也是作前端開發的短板之一,值得咱們警醒。
  9. 幸運的是,TypeScript 的出現很好地彌補了 JavaScript 在靜態類型檢查方面的缺陷。它爲 JavaScript 提供了良好的類型檢查支持,並且可以編譯成標準的 JavaScript。
  10. 目前, Angular 已經使用 TypeScript 重構了代碼,另外一大前端框架 Vue 的新版本也將使用 TypeScript 進行重構。在可預見的將來,TypeScript 將成爲前端開發者必須掌握的開發語言之一。
  11. 那麼, TypeScript 究竟有哪些特性使得它成爲你們的」剛需「?
    • 第一,類型檢查。TypeScript 會在編譯代碼時進行嚴格的靜態類型檢查,這意味着你能夠在編碼階段發現可能存在的隱患,而沒必要把它們帶到線上。
    • 第二,語言擴展。TypeScript 會包括來自 ES 6 和將來提案中的特性,好比異步操做和裝飾器;也會從其餘語言借鑑某些特性,好比接口和抽象類。
    • 第三,工具屬性。TypeScript 可以編譯成標準的 JavaScript,能夠在任何瀏覽器、操做系統上運行,無需任何運行時的額外開銷。從這個角度上講,TypeScript 更像是一個工具,而不是一門獨立的語言。
    • 除此以外,TypeScript 還能夠幫助團隊重塑「類型思惟」,接口提供方將被迫去思考 API 的邊界,他們將從代碼的編寫者蛻變爲代碼的設計者。

第一個TypeScript 實例

//var [變量名] : [類型] = 值;
const hello : string = "Hello World!"
console.log(hello)
複製代碼

TypeScript 安裝【即在cmd中將ts編譯成js的命令】

  1. 本地環境安裝 npm 工具,使用如下命令來安裝:
npm install -g typescript
複製代碼
  1. 安裝後咱們使用 tsc 命令來執行 TypeScript 的相關代碼:
//如下是查看版本號
$ tsc -v
Version 3.2.2
複製代碼
  1. 而後咱們新建一個 test.ts
var message:string = "Hello World" 
console.log(message)
複製代碼
  1. 執行 tsc 命令將 TypeScript 轉換爲 JavaScript 代碼:
tsc test.ts
複製代碼
  1. 這時候再當前目錄下(與 test.ts 同一目錄)就會生成一個 test.js 文件,代碼以下:
var message = "Hello World";
console.log(message);
複製代碼
  1. 使用 node 命令來執行 test.js 文件:
$ node test.js 
Hello World
複製代碼
  1. TypeScript 轉換爲 JavaScript 過程以下圖: npm

  2. 咱們能夠同時編譯多個 ts 文件:編程

tsc file1.ts, file2.ts, file3.ts
複製代碼
  1. tsc 經常使用編譯參數以下表所示:
1. --help顯示幫助信息
2. --module載入擴展模塊
3. --target設置 ECMA 版本
4. --declaration額外生成一個 .d.ts 擴展名的文件。
    tsc ts-hw.ts --declaration生成 ts-hw.d.ts、ts-hw.js 兩個文件。
5. --removeComments刪除文件的註釋
6. --out編譯多個文件併合併到一個輸出的文件
7. --sourcemap生成一個 sourcemap (.map) 文件。sourcemap 是一個存儲源代碼與編譯代碼對應位置映射的信息文件。
8. --module noImplicitAny在表達式和聲明上有隱含的 any 類型時報錯
9. --watch在監視模式下運行編譯器。會監視輸出文件,在它們改變時從新編譯。
複製代碼

TypeScript元祖&聯合類型

  1. 數組中的元素通常認爲都是相同數據類型的
  2. 若是存儲的元素數據類型不一樣,則須要使用元組
  3. 至於元祖的操做,和數組並沒有差異
  4. 聯合類型:經過管道(|)將變量設置多種類型
var val:string|number 
val = 12 
console.log("數字爲 "+ val) 
val = "Runoob" 
console.log("字符串爲 " + val)
複製代碼
  1. 也能夠將聯合類型做爲函數參數使用
function disp(name:string|string[]) { 
    if(typeof name == "string") { 
        console.log(name) 
    } else { 
        var i; 
        for(i = 0;i<name.length;i++) { 
            console.log(name[i])
        } 
    } 
} 
複製代碼
  1. 聯合類型數組var arr:number[]|string[]

TypeScript接口

接口是一系列抽象方法的聲明,是一些方法特徵的集合,這些方法都應該是抽象的,須要由具體的類去實現json

一個簡單的接口

/** TypeScript 接口定義以下 interface interface_name { } 如下實例中,咱們定義了一個接口 IPerson, 接着定義了一個類型爲IPerson變量 customer customer 實現了接口 IPerson 的屬性和方法。 注意接口不能轉換爲 JavaScript。 它只是 TypeScript 的一部分。 */
interface IPerson { 
    firstName:string, 
    lastName:string, 
    sayHi: ()=>string 
} 
 
var customer:IPerson = { 
    firstName:"Tom",
    lastName:"Hanks", 
    sayHi: ():string =>{return "Hi there"} 
} 
 
console.log("Customer 對象 ") 
console.log(customer.firstName) 
console.log(customer.lastName) 
console.log(customer.sayHi())  
複製代碼

聯合類型和接口

interface RunOptions { 
    program:string; 
    commandline:string[]|string|(()=>string); 
} 
 
// commandline 是字符串
var options:RunOptions = {program:"test1",commandline:"Hello"}; 
console.log(options.commandline)  
 
// commandline 是字符串數組
options = {program:"test1",commandline:["Hello","World"]}; 
console.log(options.commandline[0]); 
console.log(options.commandline[1]);  
 
// commandline 是一個函數表達式
options = {program:"test1",commandline:()=>{return "**Hello World**";}}; 
 
var fn:any = options.commandline; 
console.log(fn());
複製代碼

接口和數組

/** 接口中能夠將數組的索引值和元素設置爲不一樣類型, 索引值能夠是數字或字符串 */
interface namelist { 
   [index:number]:string 
} 
// 錯誤元素 1: 不是 string 類型
var list2:namelist = ["John",1,"Bran"] 

interface ages { 
   [index:string]:number 
} 
var agelist:ages; 
agelist["John"] = 15  // 正確 
agelist[2] = "nine"   // 錯誤
複製代碼

接口繼承

/** 接口繼承就是說接口能夠經過其餘接口來擴展本身。 Typescript 容許接口繼承多個接口。 繼承使用關鍵字 extends。 */

//單接口繼承語法格式:
Child_interface_name extends super_interface_name

//多接口繼承語法格式:
Child_interface_name extends super_interface1_name,
super_interface2_name,…,super_interfaceN_name

//單繼承實例
interface Person { 
   age:number 
} 
interface Musician extends Person { 
   instrument:string 
} 
var drummer = <Musician>{}; 
drummer.age = 27 
drummer.instrument = "Drums" 
console.log("年齡: "+drummer.age)
console.log("喜歡的樂器: "+drummer.instrument)

//多繼承實例
interface IParent1 { 
    v1:number 
} 
interface IParent2 { 
    v2:number 
} 
interface Child extends IParent1, IParent2 { } 
var Iobj:Child = { v1:12, v2:23} 
console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
複製代碼

TypeScript

類描述了所建立的對象共同的屬性和方法。後端

類的定義

//語法:class class_name { }
class Person {}
//編譯成js就是:
var Person = /** @class */ (function () {
    function Person() {
    }
    return Person;
}());

//建立類的數據成員
class Car {  
    engine:string; // 字段 
    constructor(engine:string) { // 構造函數
        this.engine = engine 
    }     
    disp():void { // 方法 
        console.log("發動機爲 : "+this.engine) 
    } 
}
//建立實例
var obj = new Car("Engine 1")
obj.disp()
複製代碼

類的繼承

子類除了不能繼承父類的私有成員(方法和屬性)和構造函數,其餘的均可以繼承。TypeScript 一次只能繼承一個類,不支持繼承多個類,但 TypeScript 支持多重繼承(A 繼承 B,B 繼承 C)。

//語法:class child_class_name extends parent_class_name
/** 下面實例中建立了 Shape 類, Circle 類繼承了 Shape 類, Circle 類能夠直接使用 Area 屬性 */
class Shape { 
   Area:number   
   constructor(a:number) { 
      this.Area = a 
   } 
} 
class Circle extends Shape { 
   disp():void { 
      console.log("圓的面積: "+this.Area) 
   } 
}
var obj = new Circle(223); 
obj.disp()

/** 類繼承後,子類能夠對父類的方法從新定義,這個過程稱之爲方法的重寫。 其中super關鍵字是對父類的直接引用,該關鍵字能夠引用父類的屬性和方法。 */
class PrinterClass { 
   doPrint():void {
      console.log("父類的 doPrint() 方法。") 
   } 
} 
class StringPrinter extends PrinterClass { 
   doPrint():void { 
      super.doPrint() // 調用父類的函數
      console.log("子類的 doPrint()方法。")
   } 
}
複製代碼

static 關鍵字

static 關鍵字用於定義類的數據成員(屬性和方法)爲靜態的,靜態成員能夠直接經過類名調用。

class StaticMem {  
   static num:number;    
   static disp():void { 
      console.log("num 值爲 "+ StaticMem.num) 
   } 
} 
StaticMem.num = 12     // 初始化靜態變量
StaticMem.disp()       // 調用靜態方法

//上述代碼編譯成js就是
var StaticMem = /** @class */ (function () {
    function StaticMem() {
    }
    StaticMem.disp = function () {
        console.log("num 值爲 " + StaticMem.num);
    };
    return StaticMem;
}());
StaticMem.num = 12; // 初始化靜態變量
StaticMem.disp(); // 調用靜態方法
複製代碼

instanceof 運算符

instanceof 運算符用於判斷對象是不是指定的類型,若是是返回 true,不然返回 false

class Person{ } 
var obj = new Person() 
var isPerson = obj instanceof Person; 
console.log("obj 對象是 Person 類實例化來的嗎? " + isPerson);
複製代碼

訪問控制修飾符

可使用訪問控制符來保護對類、變量、方法和構造方法的訪問

/** public(默認) : 公有,能夠在任何地方被訪問。 protected : 受保護,能夠被其自身以及其子類和父類訪問。 private : 私有,只能被其定義所在的類訪問。 */
class Encapsulate { 
   str1:string = "hello" 
   private str2:string = "world" 
}
 
var obj = new Encapsulate() 
console.log(obj.str1)     // 可訪問 
console.log(obj.str2)   // 編譯錯誤, str2 是私有的
複製代碼

類和接口

類能夠實現接口,使用關鍵字 implements

interface ILoan { 
   interest:number 
} 
 
class AgriLoan implements ILoan { 
   interest:number 
   rebate:number 
   constructor(interest:number,rebate:number) { 
      this.interest = interest 
      this.rebate = rebate 
   } 
} 
 
var obj = new AgriLoan(10,1) 
console.log("利潤爲 : "+obj.interest+",抽成爲 : "+obj.rebate )
複製代碼

TypeScript 對象

  1. 乍一看,好像和普通的JavaScript對象沒啥區別
/** 對象是包含一組鍵值對的實例。 值能夠是標量、函數、數組、對象等,以下實例 */
var object_name = { 
    key1: "value1", // 標量
    key2: "value",  
    key3: function() {
        // 函數
    }, 
    key4:["content1", "content2"] //集合
}
console.log(object_name.key1) 
複製代碼
  1. 再來看下面的實例,他們仍是不同滴【TypeScript 類型模板】
//假如咱們在 JavaScript 定義了一個對象:
var sites = { 
   site1:"Runoob", 
   site2:"Google" 
};
//這時若是咱們想在對象中添加方法,能夠作如下修改:
sites.sayHello = function(){ return "hello";}

//若是在 TypeScript 中使用以上方式則會出現編譯錯誤,
//由於Typescript 中的對象必須是特定類型的實例。

--------------------------------------------------
//在typescript中得以下定義:
var sites = {
    site1: "Runoob",
    site2: "Google",
    sayHello: function () { } // 類型模板
};
sites.sayHello = function () {
    console.log("hello " + sites.site1);
};
sites.sayHello();

--------------------------------------------------
/** 鴨子類型(Duck Typing): 是動態類型的一種風格,是多態(polymorphism)的一種形式。 在這種風格中,一個對象有效的語義, 不是由繼承自特定的類或實現特定的接口, 而是由"當前方法和屬性的集合"決定。 能夠這樣表述: "當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子, 那麼這隻鳥就能夠被稱爲鴨子。" */
interface IPoint { 
    x:number 
    y:number 
} 
function addPoints(p1:IPoint,p2:IPoint):IPoint { 
    var x = p1.x + p2.x 
    var y = p1.y + p2.y 
    return {x:x,y:y} 
} 
 
// 正確
var newPoint = addPoints({x:3,y:4},{x:5,y:1})  
 
// 錯誤 
var newPoint2 = addPoints({x:1},{x:4,y:3})
複製代碼

TypeScript 命名空間

  1. 命名空間一個最明確的目的就是解決重名問題。TypeScript 中命名空間使用 namespace 來定義
//語法以下:
namespace SomeNameSpaceName { 
   export interface ISomeInterfaceName {      }  
   export class SomeClassName {      }  
}

/** 以上定義了一個命名空間 SomeNameSpaceName, 若是咱們須要在外部能夠調用 SomeNameSpaceName 中的類類和接口, 則須要在類和接口添加 export 關鍵字。 要在另一個命名空間調用語法格式爲: */
SomeNameSpaceName.SomeClassName;

/** 若是一個命名空間在一個單獨的 TypeScript 文件中, 則應使用三斜槓 /// 引用它,語法格式以下: */
/// <reference path = "SomeFileName.ts" />
複製代碼
  1. 如下實例演示了命名空間的使用,定義在不一樣文件中
IShape.ts 文件代碼:
namespace Drawing { 
    export interface IShape { 
        draw(); 
    }
}

Circle.ts 文件代碼:
/// <reference path = "IShape.ts" /> 
namespace Drawing { 
    export class Circle implements IShape { 
        public draw() { 
            console.log("Circle is drawn"); 
        }  
    }
}

Triangle.ts 文件代碼:
/// <reference path = "IShape.ts" /> 
namespace Drawing { 
    export class Triangle implements IShape { 
        public draw() { 
            console.log("Triangle is drawn"); 
        } 
    } 
}

TestShape.ts 文件代碼:
/// <reference path = "IShape.ts" />   
/// <reference path = "Circle.ts" /> 
/// <reference path = "Triangle.ts" />  
function drawAllShapes(shape:Drawing.IShape) { 
    shape.draw(); 
} 
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());

使用 tsc 命令編譯以上代碼:
tsc --out app.js TestShape.ts 
複製代碼
  1. 命名空間支持嵌套,即你能夠將命名空間定義在另一個命名空間裏頭
namespace namespace_name1 { 
    export namespace namespace_name2 {
        export class class_name {    } 
    } 
}
//成員的訪問使用點號 . 來實現,以下實例:

//Invoice.ts 文件代碼:
namespace Runoob { 
   export namespace invoiceApp { 
      export class Invoice { 
         public calculateDiscount(price: number) { 
            return price * .40; 
         } 
      } 
   } 
}

//InvoiceTest.ts 文件代碼:
/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice(); 
console.log(invoice.calculateDiscount(500));
複製代碼

TypeScript 模塊

  • TypeScript 模塊的設計理念是能夠更換的組織代碼。
  • 模塊是在其自身的做用域裏執行,並非在全局做用域,這意味着定義在模塊裏面的變量、函數和類等在模塊外部是不可見的,除非明確地使用 export 導出它們。相似地,咱們必須經過 import 導入其餘模塊導出的變量、函數、類等。
  • 兩個模塊之間的關係是經過在文件級別上使用 import 和 export 創建的。
  • 模塊使用模塊加載器去導入其它的模塊。
  • 在運行時,模塊加載器的做用是在執行此模塊代碼前去查找並執行這個模塊的全部依賴。
  • 你們最熟知的JavaScript模塊加載器是服務於 Node.jsCommonJS 和服務於 Web 應用的 Require.js
  • 此外還有有 SystemJsWebpack
模塊導出使用關鍵字 export 關鍵字,語法格式以下:
// 文件名 : SomeInterface.ts 
export interface SomeInterface { 
   // 代碼部分
}

要在另一個文件使用該模塊就須要使用 import 關鍵字來導入:
import someInterfaceRef = require("./SomeInterface")
複製代碼
  • 實例演示
//IShape.ts 文件代碼:
/// <reference path = "IShape.ts" /> 
export interface IShape { 
   draw(); 
}
//Circle.ts 文件代碼:
import shape = require("./IShape"); 
export class Circle implements shape.IShape { 
   public draw() { 
      console.log("Cirlce is drawn (external module)"); 
   } 
}
//Triangle.ts 文件代碼:
import shape = require("./IShape"); 
export class Triangle implements shape.IShape { 
   public draw() { 
      console.log("Triangle is drawn (external module)"); 
   } 
}
//TestShape.ts 文件代碼:
import shape = require("./IShape"); 
import circle = require("./Circle"); 
import triangle = require("./Triangle");  
 
function drawAllShapes(shapeToDraw: shape.IShape) {
   shapeToDraw.draw(); 
} 
 
drawAllShapes(new circle.Circle()); 
drawAllShapes(new triangle.Triangle());
複製代碼

TypeScript 聲明文件[declare]

  • TypeScript 做爲 JavaScript 的超集,在開發過程當中不可避免要引用其餘第三方的 JavaScript 的庫。
  • 雖然經過直接引用能夠調用庫的類和方法,可是卻沒法使用TypeScript 諸如類型檢查等特性功能。
  • 爲了解決這個問題,須要將這些庫裏的函數和方法體去掉後只保留導出類型聲明,而產生了一個描述 JavaScript 庫和模塊信息的聲明文件。
  • 經過引用這個聲明文件,就能夠借用 TypeScript 的各類特性來使用庫文件了。
假如咱們想使用第三方庫,好比 jQuery,
咱們一般這樣獲取一個 id 是 foo 的元素:
$('#foo');
// 或
jQuery('#foo');

可是在 TypeScript 中,
咱們並不知道 $ 或 jQuery 是什麼東西:
jQuery('#foo');
// index.ts(1,1): error TS2304: Cannot find name 'jQuery'.

這時,咱們須要使用 declare 關鍵字來定義它的類型,
幫助 TypeScript 判斷咱們傳入的參數類型對不對:
declare var jQuery: (selector: string) => any;
jQuery('#foo');

declare 定義的類型只會用於編譯時的檢查,編譯結果中會被刪除。
上例的編譯結果是:
jQuery('#foo');
複製代碼
  • 聲明文件
以 .d.ts 爲後綴,例如:runoob.d.ts
聲明文件或模塊的語法格式以下:
declare module Module_Name {
}

TypeScript 引入聲明文件語法格式:
/// <reference path = " runoob.d.ts" />

固然,不少流行的第三方庫的聲明文件不須要咱們定義了,
好比 jQuery 已經有人幫咱們定義好了:
jQuery in DefinitelyTyped。
複製代碼
  • 實例
如下定義一個第三方庫來演示:
CalcThirdPartyJsLib.js 文件代碼:
var Runoob;  
(function(Runoob) {
    var Calc = (function () { 
        function Calc() { 
        } 
    })
    Calc.prototype.doSum = function (limit) {
        var sum = 0; 
 
        for (var i = 0; i <= limit; i++) { 
            sum = sum + i; 
        }
        return sum; 
    }
    Runoob.Calc = Calc; 
    return Calc; 
})(Runoob || (Runoob = {})); 
var test = new Runoob.Calc();

若是咱們想在 TypeScript 中引用上面的代碼,則須要設置聲明文件 Calc.d.ts,代碼以下:
Calc.d.ts 文件代碼:
declare module Runoob { 
   export class Calc { 
      doSum(limit:number) : number; 
   }
}

聲明文件不包含實現,它只是類型聲明,把聲明文件加入到 TypeScript 中:
CalcTest.ts 文件代碼:
/// <reference path = "Calc.d.ts" /> 
var obj = new Runoob.Calc(); 
// obj.doSum("Hello"); // 編譯錯誤
console.log(obj.doSum(10));

下面這行致使編譯錯誤,由於咱們須要傳入數字參數:
obj.doSum("Hello");
複製代碼

學完TypeScript,來看下谷歌FLOW

  1. 做用: javascript類型檢查

  2. 使用步驟

安裝flow, npm init -y -> cnpm i flow-bin -D
package.json中增長執行指令, "flow": "flow"
初始化flow配置文件, npm run flow init
[ignore]: 忽略檢測類型的文件
[include]: 須要檢測類型的文件


在項目中使用以下:
A. 經過註釋(不推薦)
// @flow 註釋以後的內容才能被flow檢測
/*: number */ 在須要檢測的內容這樣註釋, 說明其中類型
  // @flow
  let a /*: number */ = 3;
  a = 'cc'
  console.log(a)

B. 直接改寫js結構(須要babel, 相似ts語法了)
安裝bebel, cnpm i babel-cli babel-preset-flow -D
建立.babelrc文件,
  {
    "presets": [
      "flow"
    ]
  }

package.json文件中添加 "build": "babel ./src -d ./dist"
npm run build 經過babel把新增長的: number去除掉, 方便轉碼上線(與下面的指令區分開來)
  let a: number = 3;
  a = 'abc';
  console.log(a);

npm run flow 仍是會檢測數據類型
執行npm run flow, 檢測js內容
複製代碼
  1. Flow中的數據類型
number類型:
 能夠賦值的類型——數值, NaN, Infinity 
 let a: number = NaN
 
 string類型
 
 Boolean類型
 
 void類型: 就是js中的undefined
 
 null
 
 Array類型(須要指定array的元素類型) :
 let arr: Array<number> = []
 
 any類型
 let test: any = 任意數據
複製代碼
  1. Flow的函數類型
// 聲明一個函數類型, 函數參數聲明類型, 返回值也要聲明類型
  const sum = (arr: Array<number>): number => {
    let result = 0;
    arr.forEach(item => {
      result += item;
    });
    return result;
  };

  // 當聲明一個函數變量時, 說明這個變量是函數, 
  //參數兩個爲數字, 返回值爲數字
  let temp = (a: number, b:number) => number;
  // 最多見的ajax, 參數是函數時, 同時箭頭後面表明返回值類型,
  // 不寫默認是undefined
  const ajax = (callback: (data: Object) => void) {

  }

//Maybe類型
  // 問號表明能夠是null或者undefined, 函數沒有聲明返回值, 
  // 即返回值也能夠是undefined
  const test = (a: ?number) {
    console.log(a)
  } 

//類型的或操做
  // 就是或操做, 二者類型選擇一個
  let a = number|string = 10;
  a = 'abc'

//對象類型
  const ajax = (option: { url:string, type: string, 
      success:(data: Object) => void }) {

  }
  ajax()// 報錯, 由於函數參數是對象
複製代碼
相關文章
相關標籤/搜索