關於 TS
來自專欄那些年我不清楚的問題13 人贊了文章
TS 是什麼
TypeScript 是微軟開發的開源的編程語言,是 JavaScript 的一個超集,支持可選的(可以寫普通 JS 代碼也可寫 TS)靜態類型檢查,吸收 ES6 精華的同時又加入新的特性。可見 TS 主要能幹兩件事:
- 類型檢查
- 對 ES6,ES7 ... 支持的同時又實現自己了一些高級特性
JS 本身就是一個弱語言語言,即變數的類型是不確定的。例如:
let x = 5;x = x + hello world; // 5 hello world
當然弱類型也有他的好處,例如非常靈活。
但是,對於大型項目來說,強類型更有利,因為那時候的數據就不止 xyz 了,四面八方的未知類型數據過來,而且類型也隨時可能被改變,這就非常蛋疼了(不可控),而強類型支持提前定義類型,在編譯時(配合 IDE 寫代碼時)就能發現類型(不止是類型)錯誤,可以降低系統的複雜度,TS 應勢而生。
TS 中的類型
字元串
let myName: string = weixian;myName = 18; // 再賦值非 string 的值就會報錯
數組
其實常規意義上的數組定義是:一組具有相同特徵的有序數據集合。大多數語言也是這麼實現的,但 JS 中的數據是個例外,裡面啥都可以放,TS 解決這個問題,定義數據的方式如下:
let arr: number[] = [1,2,3];
也可以使用泛型的方式去定義:
let arr: Array<number> = [1,2,3];
枚舉
使用枚舉我們可以定義一些有名字的數字常量,例如:
enum Color { Red, Green, Blue };console.log(Color.Blue);// 2let colorName: string = Color[2];// 可以由枚舉值反映射出枚舉成員的名字console.log(colorName);// Blue
枚舉不就是列印個數字?這玩意到底有啥用呢?下面舉個例子說明。
鍵盤上的上下左右鍵,我們想按不同的鍵進行對應的操作,可寫代碼如下:
switch(keyCode) { case 38: // 上 break; case 40: // 下 break; case 37: // 左 break; case 39: // 右 break; default: // 非上下左右 break;}
發沒發現上面代碼有個小問題,直接用數字判斷使代碼非常的不明朗,我怎麼知道 38 就是「上」,40 就是下呢?所以我們改寫代碼如下:
let direction = { Up: 38, Down: 40, Left: 37, Right: 39};// 這樣 switch 中的代碼比剛才好多了switch (keyCode) { case direction.Up: // 上 break; case direction.Down: // 下 break; case direction.Left: // 左 break; case direction.Right: // 右 break; default: // 非上下左右 break;}
那麼還有沒有更簡便的辦法實現上面功能呢,這時枚舉就出現了,代碼如下:
enum direction { Up = 38, Down = 40, Left = 37, Right = 39,}// switch 代碼同上
Any
有時候,我們會想要為那些在編程階段還不清楚類型的變數指定一個類型需要 any
let notSure: any = 4;notSure = "maybe a string type";notSure = 111;
Never
返回 never 的函數必須存在無法達到的終點
function error(message: string): never { throw new Error(message);}
Object
function test(o: object | null): void { console.log(o)};test({age: 18});test(null);test(18); // Error
聯合類型
可以規定多種類型,例如函數中參數我想 string 和 number 都可以接收:
function test(con: string | number) { console.log(con);}test("aaayang");test(666);
交叉類型
interface T1 { sex: boolean; name: string;}interface T2 { age: number;}type T = T1 & T2;let test: T = { sex: true, name: "aaa", age: 18}
自定義類型
class Person { name: string; age: number;}let weixian: Person = new Person();// 這裡的 weixian 只能有兩種類型的屬性weixian.name = "weixian";weixian.age = 18;
TS 中的其他特性
類型斷言
一個函數接收 string 或 number,並返回接收參數的 length,這時候我們直接返回是通不過類型檢測的,因為有可能傳過來的實參是 number ,這時候並沒有 length 屬性,這時候就用到了類型斷言:
function getLength(something: string | number): number { // 兩種斷言方法是等價的,注意當你在 TS 里使用 JSX 時,只有 as 語法斷言是被允許的,因為 TS 1.6 才開始支持 JSX // return something.length;// 靜態類型檢查報錯 // return (<string>something).length; // 斷言方法一 return (something as string).length; // 斷言方法二}
函數聲明的兩種方式
function test(x: number, y: number): number { return x + y;}test(1, 2);
第二種方式:
// 等號左邊描述了函數的參數及返回值let test: (x: number, y: number) => number = function (x:number, y: number):number { return x + y;};console.log( test(1, 2) );
上面可以簡寫成一下形式:
// 自動做了類型推斷let test: (x: number, y: number) => number = function (x, y) { return x + y;};console.log(test(1, 2));
函數重載
可以為同一個函數提供多個函數類型定義,具體參見鏈接。
function test(x: number, y: number): number;function test(x: string, y: string): string;function test(x: any, y: any): any { // 這裡是參考的上面的定義的 if(typeof x == number) { return x * y; } else { return x + y; }}test(aaa, bbbb);test(1, 2);
解構賦值
// 解構賦值應用於函數傳參function f({ name, age }: { name: string, age?: number }): void { console.log(name, age);// "aaayang", undefined}let data = { name: "aaayang"};f(data);
Rest and Spread
// 用來聲明任意數量的方法參數function test(...args) { args.forEach(function(arg) { console.log(arg); });}test(1, 2 ,3);
// ts會報錯,但編譯出JS可執行function test(a, b, c) { console.log(a); console.log(b); console.log(c);}let args = [5, 6, 7];test(...args);
Interface
介面的作用就是去描述結構,類,函數的形態
// 使用介面interface inforCon { name: string; age?: number; readonly job: string;// 只讀}// 穿入參數infor要符合介面定義function printInfor(infor: inforCon) { console.log(infor.name); // infor.job = "司機";// 不能修改}let myInfor = { name: "aaayang", job: "it"};printInfor(myInfor);
用介面描述類
interface Animal { eat(): void;}// 用介面聲明方法,實現Animal介面,必須實現該介面中的方法class Sheep implements Animal { eat() { console.log("I eat grass"); }}class Tiger implements Animal { eat() { console.log("I eat meat"); }}
TS 中的類
class Person { public name: string; // 默認 public protected age: number; // 父類極其子類中 constructor(name: string, age: number) { this.name = name; this.age = age; } say():void { console.log(hello + this.name); }}
受保護的屬性只能在自身或子類中獲取到
let p1: Person = new Person(aaa, 18);p1.say();console.log(p1.age); // 受保護的 age 是拿不到的
子類實例使用父的受保護屬性:
class Student extends Person { constructor(name: string, age:number) { super(name, age); } getAge(): number { return this.age; }}let s1: Student = new Student(bbb, 8);console.log(s1.getAge());
關於類還有其他更多的特性,點此鏈接
關於泛型
需求:使返回值的類型與傳入參數的類型是相同的
明確傳入類型的情況下:
function identity1(arg: number): number { return arg;}
不知道傳入類型的情況下:
function identity2(arg: any): any { // 使用any,傳入和返回類型不一樣也是可以的,不是我們希望的,不完全可控 return arg;}
解決,泛型:以適用於多個類型
// <T>幫助我們捕獲用戶傳入的類型,arg:T使用捕獲的類型,然後返回捕獲的類型function identity3<T>(arg: T): T { return arg;}
// 泛型調用identity<string>("myString");// 利用了類型推論 -- 即編譯器會根據傳入的參數自動地幫助我們確定T的類型identity("myString");
泛型函數
// 把泛型變數T當做類型的一部分使用,而不是整個類型function test<T>(arg: T[]): T[] { console.log(arg.length); // 元素類型是T類型的數組 return arg;}test([5, 6]);test([a, b]);
泛型介面
interface Fn { // 規定泛型類型,函數參數,返回值 <T>(arg: T): T;}function test<T>(arg: T): T { return arg;}// 使用泛型介面let myTest: Fn = test;console.log( myTest(5) );// 5
泛型類
class Person { constructor(public name: string) {// public相當於外部定義name this.name = name; } eat() { // 上面public這裡才可以this.name console.log(this.name + " is eating..."); }}let workers: Array<Person> = [];// 指定數組只能放某一個類型的元素workers[0] = new Person("Aaayang");
關於類型定義文件
TypeScript 的聲明文件是一個以 .d.ts 為後綴的 TypeScript 代碼文件,它的作用是描述一個 ????JavaScript 模塊(廣義上的)內所有導出介面的類型信息。幫助開發者在TS中使用已有的 JS 工具包,如:jQuery,React,或者自己的方法庫(需要自己定義)。
如何聲明和使用類型定義文件?
通過 DefinitelyTyped 或 TypeSearch 查找對應的 Definition,然後通過 npm install --save@types/jquery進行安裝,或通過 typings 進行??管理 Definition,例如 typings search --name jquery
注意:主流的框架或者插件是有@type 的實現,但是也有一些框架是沒有實現的,導致了很多小玩意在 TS 中玩不了,需要自己聲明 d.ts 文件。
以上只是 TS 很少的一部分,它還有很多更高級的東西,一起學習吧!
題圖來源:Tim Gouw
推薦閱讀:
※ts-node 下錯誤堆棧問題排查小記
※Vue + TypeScript踩坑(初始化項目)
※合格前端第十二彈-TypeScript + 大型項目實戰
※微軟發起TSDoc項目試圖規範文檔格式
TAG:TypeScript |