簡介
本篇文章主要是為了給讓大家了解下Typescript
這里將會講到大家關心的幾個問題匾南,簡單先簡紹了幾個與js不同的ts的語法偷线,來探討ts和傳統(tǒng)js的區(qū)別
然后從網(wǎng)絡上收集整理了一些使用和不使用ts的意見,探討我們應不應該使用ts,以及ts的適用場景
[TOC]
一挺狰、介紹
特點
- JavaScript 的超集
- 增加了靜態(tài)類型系統(tǒng)
- 為大型軟件開發(fā)而設計的
- 最終編譯產(chǎn)生 JavaScript
安裝 TypeScript
執(zhí)行npm install -g typescript
然后就可以在任何地方編譯ts文件tsc holle.ts
簡單的例子
將下面代碼復制到hello.ts
中, 其中使用 : 指定變量的類型
function sayHello(person: string) {
return 'Hello, ' + person;
}
let user = 'Tom';
console.log(sayHello(user));
然后執(zhí)行
tsc holle.ts
、
這時候會生成一個編譯好的文件hello.js
:
function sayHello(person) {
return 'Hello, ' + person;
}
var user = 'Tom';
console.log(sayHello(user));
報錯
編譯下段代碼
// holle.ts
function sayHello(person: string) {
return 'Hello, ' + person;
}
let user = [0, 1, 2];
console.log(sayHello(user));
編譯器報錯
index.ts(6,22): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.
因為TypeScript 編譯的時候會進行靜態(tài)檢查买窟,如果發(fā)現(xiàn)有錯誤丰泊,就會報錯
但注意,即使報錯蔑祟,也會生成相應的js文件
二趁耗、與js異同
1沉唠、變量聲明
和es6一樣疆虚,有l(wèi)et和const
2、基礎數(shù)據(jù)類型
bool满葛、number径簿、string、undefined嘀韧、arr篇亭、obj都有
不同的:
- 元組
允許表示一個已知元素數(shù)量和類型的數(shù)組
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
- 枚舉
像C#等其它語言一樣,使用枚舉類型可以為一組數(shù)值賦予友好的名字锄贷。
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
- Any
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
還不清楚類型的變量指定一個類型
- Void
void類型像是與any類型相反译蒂,它表示沒有任何類型曼月。
function warnUser(): void {
console.log("This is my warning message");
}
- never
表示的是那些永不存在的值的類型。
// 返回never的函數(shù)必須存在無法達到的終點
function error(message: string): never {
throw new Error(message);
}
// 推斷的返回值類型為never
function fail() {
return error("Something failed");
}
// 返回never的函數(shù)必須存在無法達到的終點
function infiniteLoop(): never {
while (true) {
}
}
- 類型斷言
< >表示柔昼, 通常這會發(fā)生在你清楚地知道一個實體具有比它現(xiàn)有類型更確切的類型哑芹。
et someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
- 多種類型(聯(lián)合類型)
可以用|隔開,比如number | string表示可以是number或string類型
3. 接口
TypeScript的核心原則之一是對值所具有的結構進行類型檢查捕透,接口的作用就是為這些類型命名和為你的代碼或第三方代碼定義契約聪姿。
- 簡單的接口
定義傳入的參數(shù)
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
- 可選接口
參數(shù)可選
interface SquareConfig {
color?: string;
width?: number;
}
- 只讀屬性
傳入?yún)?shù)只讀
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
- 描述函數(shù)
定義函數(shù)輸入輸出
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
- 實現(xiàn)接口
在類中實現(xiàn)接口
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
- 繼承接口
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
4. 類
定義了一件事物的抽象特點,包含它的屬性和方法
面向對象(OOP)的三大特性:封裝乙嘀、繼承末购、多態(tài)
對象實例通過new生成
- 封裝
將對數(shù)據(jù)的操作細節(jié)隱藏起來,只暴露對外的接口虎谢。外界調用端不需要(也不可能)知道細節(jié)盟榴,就能通過對外提供的接口來訪問該對象,同時也保證了外界無法任意更改對象內部的數(shù)據(jù)
- 多態(tài)
由繼承而產(chǎn)生了相關的不同的類婴噩,對同一個方法可以有不同的響應曹货。比如 Cat 和 Dog 都繼承自 Animal,但是分別實現(xiàn)了自己的 eat 方法讳推。此時針對某一個實例顶籽,我們無需了解它是 Cat 還是 Dog,就可以直接調用 eat 方法银觅,程序會自動判斷出來應該如何執(zhí)行 eat
- 繼承
子類繼承父類礼饱,子類除了擁有父類的所有特性外,還有一些更具體的特性
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
- 存取器(getter & setter)
用以改變屬性的讀取和賦值行為
- 修飾符(Modifiers)
修飾符是一些關鍵字究驴,用于限定成員或類型的性質镊绪。如 public 和 private
- 抽象類(Abstract Class)
抽象類是供其他類繼承的基類,抽象類不允許被實例化洒忧。抽象類中的抽象方法必須在子類中被實現(xiàn)
這個和接口有點像蝴韭,有興趣可以看下接口和抽象類的區(qū)別
5. 泛型
在像C#和Java這樣的語言中,可以使用泛型來創(chuàng)建可重用的組件熙侍,一個組件可以支持多種類型的數(shù)據(jù)榄鉴。
// 使用泛型前
function identity(arg: number): number {
return arg;
}
// 使用泛型后
function identity<T>(arg: T): T {
return arg;
}
T幫助我們捕獲用戶傳入的類型,使用后再返回類型T的值
6.使用第三方模塊
- 需要相應的聲明文件(.d.ts文件)
一般情況下在 TypeScript 中是不能”直接“使用 npm 上的模塊
不是使用 TypeScript 編寫的模塊蛉抓,也可以通過手動編寫聲明文件來兼容 TypeScript庆尘。
- 通過 npm install @types/xxx 來安裝模塊聲明文件
TypeScript 官方建立了一個名叫 DefinitelyTyped 的倉庫,任何人都可以通過 GitHub 在上面修改或者新增 npm 模塊的聲明文件
最后
還有其他類型就不一一詳細介紹了巷送,具體可以參照官方文檔(中文版)
三驶忌、使用與不使用的理由
1. 不使用的理由
- npm裝上的那些xxxjs庫都是沒有任何類型信息的
(只能使用諸如definitelytyped之類的ts定義庫)
- TS+框架會有很多坑
- 比如 :immutable.js + Typescript 坑很多
- 必須學習框架+全家桶的各種暴露出來的d.ts
- TS徹底替代babel會出問題,比如不能享受babel-plugin-import這種按需引入的Babel插件了
- 雖然聲稱可以在任何場景下替代JS,但前提是有良好的框架支撐
- vue2.5以前對TS的支持不是特別好笑跛,但Vue本身支持不錯,周邊那些東西缺沒那么好 GitHub: 2K
- react 和 Angular 本身和周邊支持良好 付魔,GitHub: 11K 和 10K
- 語法檢測和ESlint部分重復
總結聊品,項目不大,后期不用維護的項目沒有必要使用几苍,項目主要依賴庫要對TS支持良好杨刨,冷門的小項目沒有必要用TS
2. 使用的理由
偵測錯誤,提供了一套強類型的規(guī)范擦剑,統(tǒng)一團隊代碼風格妖胀,更方便準確地檢查錯誤
在項目初期就進行,類型注釋惠勒,和接口定義赚抡,方便指導開發(fā),
文檔纠屋,新人來了也可以直接看文檔接手項目
抽象涂臣,前端圈子里有這么一個流行語『自從用了Typescript之后,再也不想用JavaScript了』
靜態(tài)類型語言,在編譯的時候就能發(fā)現(xiàn)問題
方便代碼重構
比如初期定義了一個string售担,但項目進行到一半說要改成number赁遗,如果普通的js,改一個不會報錯族铆,eslint則不會識別沒有執(zhí)行到文件的類型錯誤岩四,而在TS強類型在編譯器檢驗下,在編譯時進行類型分析哥攘,改一個剖煌,其他需要改動的地方無可型盾
- antd使用的是TS
總結,這些特點還是挺誘人的逝淹,大型項目可以使用耕姊,總體來說,學習成本有栅葡,但熟悉過es6的人來說茉兰,門檻不算太高,比較類似java的風格欣簇。