【译】2019年开始使用Typescript
基于2018年Stack Overflow Developer的調(diào)研,TypeScript作為編程語言比JavaScript更受“喜愛”。TypeScript在js開發(fā)者中這么受喜愛的原因是:在你運行代碼前,添加到j(luò)avascript中的類型有助你發(fā)現(xiàn)錯誤(代碼)。TypeScript編譯器提供的錯誤可以很好的引導(dǎo)你如何修復(fù)代碼錯誤。往javascript中添加類型同時有助代碼編輯器提供一些高級的功能,例如代碼完成,項目范圍的重構(gòu)和自動模塊的導(dǎo)入。
如果你認(rèn)為TypeScript是一門全新的編程語言,那么學(xué)習(xí)它可能令人生畏。然而,TypeScript只是JavaScript的一個附加層(超集),在使用TypeScript前,你無需了解它的每個語法。TypeScript允許你通過更改文件的后綴名.js為.ts來輕松的轉(zhuǎn)換javascript文件,并且所有的代碼將作為TypeScript來正確編譯。如果你想在TypeScript文件中強(qiáng)制執(zhí)行更廣的類型覆蓋百分比,你可以將TypeScript配置得更具局限性,一旦你熟悉該語言了,你就可以完成此操作。
本文旨在帶你快速了解一個標(biāo)準(zhǔn)的TypeScript項目中會遇到的95%的場景。剩余的5%,嗯,你可以google,還有,我會在本文底部放些有用的TypeScript資源鏈接。
配置TypeScript
當(dāng)然,要開始編寫能正確編譯的TypeScript(文件),正確配置開發(fā)環(huán)境是必要的。
1、安裝TypeScript編譯器
首先,為了能夠?qū)ypeScript文件轉(zhuǎn)換成JavaScript文件,我們需要安裝TypeScript編譯器。安裝TypeScript可全局安裝(文件系統(tǒng)中安裝,可以在任何位置使用)或者本地安裝(僅在項目級別可使用)。【個人偏向后者】
# NPM Installation Method npm install --global typescript # Global installation npm install --save-dev typescript # Local installation# Yarn Installation Method yarn global add typescript # Global installation yarn add --dev typescript # Local installation 復(fù)制代碼2、確保你的編輯器設(shè)置為支持TypeScript
你需要確保正確配置了你的編輯器以使用TypeScript。比如,為了在編輯器中能更好得使用TypeScript,你需要安裝一個插件(如果你使用atom,你可以安裝 atom-typescript)。如果你使用的是VS Code編輯器,那么你不需要安裝額外的插件了,因為它內(nèi)置了TypeScript的支持。?
3、新建tsconfig.json文件
tsconfig.json文件是用來配置TypeScript項目設(shè)置。它應(yīng)該放在項目的根目錄中。該文件允許你使用不同的選項配置TypeScript編譯器。
如果你僅僅是想TypeScript生效的話,你只需要tsconfig.json文件中包含一個空J(rèn)SON對象,但是,如果你需要TypeScript編譯器的有不同的行為(比如在特定的輸出目錄中輸出編譯后的JavaScript文件),你可以有關(guān)可以配置哪些設(shè)置的(內(nèi)容)。
備注:你也可以通過運行tsc --init去生成一個tsconfig.json文件,其中為你設(shè)置了些默認(rèn)選項,還有一些被注釋掉的其他選項。
4、將TypeScript轉(zhuǎn)化為JavaScript
為了將你的TypeScript代碼轉(zhuǎn)化成JavaScript代碼,需要在控制臺上跑tsc命令。運行tsc命令將告訴TypeScript編譯器去搜索tsconfig.json文件,該文件將確定項目的根目錄以及編譯TypeScript并將.ts文件轉(zhuǎn)換為.js文件時用的選項。
為了快速驗證設(shè)置生效,你可以創(chuàng)建一個測試的TypeScript文件,然后在命令行中運行tsc,之后查看下TypeScript文件旁邊是否生成了JavaScript文件。
舉個例子,TypeScript文件如下...
const greeting = (person: string) => {console.log('Good day ' + person); }; greeting('Daniel'); 復(fù)制代碼應(yīng)該被轉(zhuǎn)換為下面這個JavaScript文件了...
var greeting = function(person) {console.log('Good day ' + person); }; greeting('Daniel'); 復(fù)制代碼如果你想TypeScript編譯器(動態(tài))監(jiān)視TypeScript文件內(nèi)容的變更,并自動將.ts文件轉(zhuǎn)換成.js文件,你可以在你項目的倉庫(命令行)中運行tsc -p。
在VS Code(編輯器)中,你可以使用??B調(diào)出一個菜單,該菜單(包含)可以在正常模式和監(jiān)視模式下運行轉(zhuǎn)換程序(分別對應(yīng)tsc:build和tsc:watch)。
了解靜態(tài)和動態(tài)類型
JavaScript附帶7種動態(tài)類型:
- Undefined
- Null
- Boolean
- Number
- String
- Symbol
- Object
上面的類型被稱為動態(tài)類型,因為它們在運行時使用。
TypeScript為JavaScript語言帶來了靜態(tài)類型,并且這些類型在編譯時(無需運行代碼)被確定。靜態(tài)類型可以預(yù)測動態(tài)類型的值,這可以幫助在無需運行代碼的情況下警告你可能出現(xiàn)的錯誤。
基本靜態(tài)類型
好吧,我們來深入研究下TypeScript的語法。以下是TypeScript中最常見的類型。
備注:我遺漏了never和object類型,因為根據(jù)我的經(jīng)驗,它們并不被經(jīng)常使用。
boolean
你已經(jīng)很了解true和false值了。
let isAwesome: boolean = true; 復(fù)制代碼string
文本數(shù)據(jù)用單引號('')或雙引號("")或后標(biāo)記(``)【也稱模版字符】包圍。
let name: string = 'Chris'; let breed: string = 'Border Collie'; 復(fù)制代碼如果你使用后標(biāo)志,該字符串被稱為模版文字,可以在里面插入表達(dá)式。
let punchline: string = 'Because it was free-range.'; let joke: string = `Q: Why did the chicken cross the road?A: ${punchline} `; 復(fù)制代碼number
任何浮點數(shù)都給定為數(shù)字類型。作為TypeScript的一部分,支持的四種類型的數(shù)字文字是二進(jìn)制,十進(jìn)制,八進(jìn)制和十六進(jìn)制。
let decimalNumber: number = 42; let binaryNumber: number = 0b101010; // => 42 let octalNumber: number = 0o52; // => 42 let hexadecimalNumber: number = 0x2a; // => 42 復(fù)制代碼備注:并不是只有你一個人對二進(jìn)制,八進(jìn)制和十六進(jìn)制數(shù)字感到困惑。
array
TypeScript中有兩種書寫數(shù)組類型的方式。第一種是[]后綴在需要查找的數(shù)組元素類型。
let myPetFamily: string[] = ['rocket', 'fluffly', 'harry']; 復(fù)制代碼另一種可替代的方式是,Array后跟要查找的數(shù)組元素類型的Array類型(使用尖括號包含)。
let myPetFamily: Array<string> = ['rocket', 'fluffly', 'harry']; 復(fù)制代碼tuple
元組是一個包含固定數(shù)量的元素和相關(guān)類型的數(shù)組。
let myFavoriteTuple: [string, number, boolean]; myFavoriteTuple = ['chair', 20, true]; // ? myFavoriteTuple = [5, 20, true]; // ? - The first element should be a string, not a number 復(fù)制代碼enum
枚舉將名稱和常量值關(guān)聯(lián),可以是數(shù)字或者字符串。當(dāng)你想一組具有關(guān)聯(lián)性的描述名稱的不同值,枚舉就很有用處了。
默認(rèn),為枚舉分配從0開始的值,接下來的值為(上一個枚舉值)加1。
enum Sizes {Small,Medium,Large, } Sizes.Small; // => 0 Sizes.Medium; // => 1 Sizes.Large; // => 2 復(fù)制代碼第一個值也可以設(shè)置為非0的值。
enum Sizes {Small = 1,Medium,Large, } Sizes.Small; // => 1 Sizes.Medium; // => 2 Sizes.Large; // => 3 復(fù)制代碼枚舉默認(rèn)是被分配數(shù)字,然而,字符串也可以被分配到一個枚舉中的。
enum ThemeColors {Primary = 'primary',Secondary = 'secondary',Dark = 'dark',DarkSecondary = 'darkSecondary', } 復(fù)制代碼any
如果變量的類型未知,并且我們并不希望類型檢查器在編譯時抱怨,則可以使用any類型。
let whoKnows: any = 4; // assigned a number whoKnows = 'a beautiful string'; // can be reassigned to a string whoKnows = false; // can be reassigned to a boolean 復(fù)制代碼在開始使用TypeScript的時,可能會頻繁使用any類型。然而,最好嘗試減少any的使用,因為當(dāng)編譯器不知道與變量相關(guān)的類型時,TypeScript的有用性會降低。
void
當(dāng)沒有與事物相關(guān)類型的時候,void類型應(yīng)該被使用。在指定不返回任何內(nèi)容的函數(shù)返回值時,最常用它。
const darkestPlaceOnEarth = (): void => {console.log('Marianas Trench'); }; 復(fù)制代碼null和undefined
null和undefined都對應(yīng)你在javascript中看到的null和undefined值的類型。這些類型在單獨使用的時候不是很有用。
let anUndefinedVariable: undefined = undefined; let aNullVariable: null = null; 復(fù)制代碼默認(rèn)情況下,null和undefined類型是其他類型的子類型,這意味著可以為string類型的變量賦值為null或者undefined。這通常是不合理的行為,所以通常建議將tsconfig.json文件中的strictNullChecks編譯器選項設(shè)置為true。將strictNullChecks設(shè)置為true,會使null和undefined需要顯示設(shè)置為變量的類型。
類型推斷
幸運的是,你不需要在代碼中全部位置指定類型,因為TypeScript具有類型推斷。類型推斷是TypeScript編譯器用來自行決定類型的(內(nèi)容)。
基本類型推斷
TypeScript可以在變量初始化期間,設(shè)置默認(rèn)參數(shù)以及確定函數(shù)返回值時推斷類型。
// Variable initialization let x = 10; // x is given the number type 復(fù)制代碼在上面的例子中,x被分配了數(shù)字,TypeScript會以number類型將x變量關(guān)聯(lián)起來。
// Default function parameters const tweetLength = (message = 'A default tweet') => {return message.length; }; 復(fù)制代碼在上面的例子中,message參數(shù)被賦予了一個類型為string的默認(rèn)值,因此TypeScript編譯器會推斷出message的類型是string,因此在訪問length屬性的時候并不會拋出編譯錯誤。
function add(a: number, b: number) {return a + b; } const result = add(2, 4); result.toFixed(2); // ? result.length; // ? - length is not a property of number types 復(fù)制代碼在上面這個例子中,因為TypeScript告訴add函數(shù),它的參數(shù)都是number類型,那么可以推斷得出返回的類型也應(yīng)該是number。
最佳通用類型推斷
從多種可能的類型中推斷類型時,TypeScript使用最佳通用類型算法來選擇適用于所有其他候選類型的類型。
let list = [10, 22, 4, null, 5]; list.push(6); // ? list.push(null); // ? list.push('nope'); // ? - type 'string' is neither of type 'number' or 'null' 復(fù)制代碼在上面的例子中,數(shù)組(list)是由number或null類型組成的,因此TypeScript只希望number或null類型的值加入數(shù)組。
類型注釋
當(dāng)類型推斷系統(tǒng)不夠用的時,你需要在變量和對象上聲明類型。
基本類型
在(上面)基本靜態(tài)類型章節(jié)的介紹中,所有的類型都使用:后跟類型名來聲明。
let aBoolean: boolean = true; let aNumber: number = 10; let aString: string = 'woohoo'; 復(fù)制代碼Arrays
在(上面)講到的array類型的章節(jié)中,arrays可以通過兩種方式的其中一種進(jìn)行注釋。
// First method is using the square bracket notation let messageArray: string[] = ['hello', 'my name is fred', 'bye'];// Second method uses the Array keyword notation let messageArray: Array<string> = ['hello', 'my name is fred', 'bye']; 復(fù)制代碼接口
將多種類型的注釋組合到一起的一種方法是使用接口。
interface Animal {kind: string;weight: number; } let dog: Animal; dog = {kind: 'mammal',weight: 10, }; // ? dog = {kind: true,weight: 10, }; // ? - kind should be a string 復(fù)制代碼類型別名
TypeScript使用Type Alias指定多個類型注釋,這事(讓人)有些疑惑?!鞠旅嬷v到】
type Animal = {kind: string;weight: number; }; let dog: Animal; dog = {kind: 'mammal',weight: 10, }; // ? dog = {kind: true,weight: 10, }; // ? - kind should be a string 復(fù)制代碼在使用接口或類型別名這方面,最佳的做法似乎是,在代碼庫保持一致情況下,通常選擇接口類型或類型別名。但是,如果編寫其他人可以使用的第三方的公共API,就要使用接口類型了。
如果你想了解更多關(guān)于type alias和interface的比較的話,我推薦你看Martin Hochel的這篇文章。
內(nèi)聯(lián)注釋
相比創(chuàng)建一個可復(fù)用的接口,有時內(nèi)聯(lián)注釋類型可能更合適。
let dog: {kind: string;weight: number; }; dog = {kind: 'mammal',weight: 10, }; // ? dog = {kind: true,weight: 10, }; // ? - kind should be a string 復(fù)制代碼泛型
某些情況下,變量的特定類型無關(guān)緊要,但是應(yīng)強(qiáng)制執(zhí)行不同變量和類型之間的關(guān)系。針對這些情況,應(yīng)該使用泛型類型。
const fillArray = <T>(len: number, elem: T) => {return new Array<T>(len).fill(elem); }; const newArray = fillArray<string>(3, 'hi'); // => ['hi', 'hi', 'hi'] newArray.push('bye'); // ? newArray.push(true); // ? - only strings can be added to the array 復(fù)制代碼上面的示例中有一個泛型類型T,它對應(yīng)于傳遞給fillArray函數(shù)的第二個參數(shù)類型。傳遞給fillArray函數(shù)的第二個參數(shù)是一個字符串,因此創(chuàng)建的數(shù)組將其所有元素設(shè)置為具有字符串類型。
應(yīng)該注意的是,按照慣例,單個(大寫)字母用于泛型類型(比如:T或K)??墒?#xff0c;并不限制你使用更具有描述性的名稱來表示你的泛型類型。下面示例就是為所提供的泛型類型使用了更具有描述性的名稱:
const fillArray = <ArrayElementType>(len: number, elem: ArrayElementType) => {return new Array<ArrayElementType>(len).fill(elem); }; const newArray = fillArray<string>(3, 'hi'); // => ['hi', 'hi', 'hi'] newArray.push('bye'); // ? newArray.push(true); // ? - only strings can be added to the array 復(fù)制代碼聯(lián)合類型
在類型可以是多種類型之一的情況下,使用|分隔符隔開不同類型的選項來使用聯(lián)合類型。
// The `name` parameter can be either a string or null const sayHappyBirthdayOnFacebook = (name: string | null) => {if (name === null) {console.log('Happy birthday!');} else {console.log(`Happy birthday ${name}!`);} }; sayHappyBirthdayOnFacebook(null); // => "Happy birthday!" sayHappyBirthdayOnFacebook('Jeremy'); // => "Happy birthday Jeremy!" 復(fù)制代碼交集類型
交集類型使用&符號將多個類型組合在一起。這和(上面的)聯(lián)合類型不同,因為聯(lián)合類型是表示結(jié)果的類型是列出的類型之一,而交集類型則表示結(jié)果的類型是所有列出類型的集合。
type Student = {id: string;age: number; }; type Employee = {companyId: string; }; let person: Student & Employee; person.age = 21; // ? person.companyId = 'SP302334'; // ? person.id = '10033402'; // ? person.name = 'Henry'; // ? - name does not exist in Student & Employee 復(fù)制代碼元組類型
元組類型使用一個:符號,其后跟一個使用中括號包含且逗號分隔的類型列表表示。
let list: [string, string, number]; list = ['apple', 'banana', 8.75]; // ? list = ['apple', true, 8.75]; // ? - the second argument should be of type string list = ['apple', 'banana', 10.33, 3]; // ? - the tuple specifies a length of 3, not 4 復(fù)制代碼可選類型
可能存在函數(shù)參數(shù)或者對象屬性是可選的情況。在這些情況下,使用?來表示這些可選值。
// Optional function parameter function callMom(message?: string) {if (!message) {console.log('Hi mom. Love you. Bye.');} else {console.log(message);} } // Interface describing an object containing an optional property interface Person {name: string;age: number;favoriteColor?: string; // This property is optional } 復(fù)制代碼有幫助的資源
本文中未涉及到的TypeScript內(nèi)容,我推薦以下的資源。
TypeScript Handbook (Official TypeScript docs)
TypeScript Deep Dive (Online TypeScript Guide)
Understanding TypeScript's Type Annotation (Great introductory TypeScript article)
原文鏈接 www.robertcooper.me/get-started…
文章首發(fā) github.com/reng99/blog…
更多內(nèi)容 github.com/reng99/blog…
總結(jié)
以上是生活随笔為你收集整理的【译】2019年开始使用Typescript的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: scrum 开发方式学习笔记
- 下一篇: git flow 使用步骤