一、TypeScript是什么
TypeScript 是擁有類型系統(tǒng)的javascript超集
可以編譯成純javascript
作用:靜態(tài)類型檢查
二、使用TypeScript的好處
1.在編輯器中提示更加友好,增加可維護性




在vscode中提示更加友好,鼠標放上去就可以看到對應(yīng)的類型,而webstorm中只有書寫的時候才能看到

2.提高代碼質(zhì)量,編譯期間解決部分隱藏問題
-
類型傳入錯誤
image.png -
參數(shù)名稱錯誤
image.png
image.png -
參數(shù)個數(shù)錯誤
image.png
可以選參數(shù)在冒號前加一個?
3.接口代替文檔


更適合于大型項目或框架類項目
三、搭建簡單編譯環(huán)境
1.全局安裝typescript
npm install -g typescript
2.tsc命令編譯文件
生成tsconfig.json文件,里邊有些默認配置
tsconfig.json文件的具體配置項可以參考
TypeScript中文網(wǎng)-編譯選項
tsc --init
添加xxx.ts文件
tsc xxx.ts
在命令行輸入以上命令,可以看見生成了一個同名的xxx.js文件,這就是編譯后的文件
四、基礎(chǔ)類型
語法
(變量/函數(shù)):類型
let x:number = 1; // 變量 x必須是number類型
// 函數(shù) 參數(shù) x 、y都需要接收number類型,同時返回值也是number類型
function add(x: number, y: number): number {
return x + y;
}
// 接口
interface LabelledValue {
label: string;
}
// 類
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
1.類型列表
| es6 | TypeScript |
|---|---|
| boolean | boolean |
| string | string |
| number | number |
| Array | Array |
| Object | Object |
| Function | Function |
| Symbol | Symbol |
| null | null |
| undefined | undefined |
| - | any |
| - | void |
| - | never |
| - | 元祖 |
| - | 枚舉 |
| - | 高級 |
2.Array
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
3.Object
Object類型的變量只是允許你給它賦任意值 - 但是卻不能夠在它上面調(diào)用任意的方法,即便它真的有這些方法
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
4.any
任何類型都可以被歸為 any 類型
使用場景:
1.有時候,我們會想要為那些在編程階段還不清楚類型的變量指定一個類型。 這些值可能來自于動態(tài)的內(nèi)容,比如來自用戶輸入或第三方代碼庫。 這種情況下,我們不希望類型檢查器對這些值進行檢查而是直接讓它們通過編譯階段的檢查。
2.在對現(xiàn)有代碼進行改寫的時候,any類型是十分有用的,它允許你在編譯時可選擇地包含或移除類型檢查。
注意:
如果我們使用 any 類型,就無法使用 TypeScript 提供的大量的保護機制。
5.void
某種程度上來說,void類型像是與any類型相反,它表示沒有任何類型。 當一個函數(shù)沒有返回值時,你通常會見到其返回值類型是 void
function warnUser(): void {
console.log("This is my warning message");
}
聲明一個void類型的變量沒有什么大用,因為你只能為它賦予undefined和null:
let unusable: void = undefined;
6. Never
never 類型表示的是那些永不存在的值的類型。 例如,never 類型是那些總是會拋出異?;蚋揪筒粫蟹祷刂档暮瘮?shù)表達式或箭頭函數(shù)表達式的返回值類型。
// 返回never的函數(shù)必須存在無法達到的終點
function error(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
7.元祖
元組類型允許表示一個已知元素數(shù)量和類型的數(shù)組,各元素的類型不必相同。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
8. 枚舉
enum類型是對JavaScript標準數(shù)據(jù)類型的一個補充。 像C#等其它語言一樣,使用枚舉類型可以為一組數(shù)值賦予友好的名字。
默認情況下,從0開始為元素編號。 你也可以手動的指定成員的數(shù)值。
1.數(shù)字枚舉
enum DevStatus {
Online,
Offline,
UnRegister,
}
編譯之后的代碼
var Status;
(function (Status) {
Status[Status["Online"] = 0] = "Online";
Status[Status["Offline"] = 1] = "Offline";
Status[Status["UnRegister"] = 2] = "UnRegister";
})(Status || (Status = {}));
打印出來

可以通過值獲取到名字,也可以通過名字獲取到值
console.log(Status.Offline); // 1
console.log(Status[1]); // Offline
2.字符串枚舉
enum Color {
Red = 'red',
Blue = 'blue'
}
編譯后的代碼
var Color;
(function (Color) {
Color["Red"] = "red";
Color["Blue"] = "blue";
})(Color || (Color = {}));

只能通過名字獲取到值
3.異構(gòu)枚舉
異構(gòu)枚舉的成員值是數(shù)字和字符串的混合:
enum Enum {
A,
B = "B",
C = 3,
D,
}
編譯后的代碼
var Enum;
(function (Enum) {
Enum[Enum["A"] = 0] = "A";
Enum["B"] = "B";
Enum[Enum["C"] = 3] = "C";
Enum[Enum["D"] = 4] = "D";
})(Enum || (Enum = {}));
打印出來

五、接口
在面向?qū)ο笳Z言中,接口是一個很重要的概念,它是對行為的抽象,而具體如何行動需要由類去實現(xiàn)。
TypeScript的核心原則之一是對值所具有的結(jié)構(gòu)進行類型檢查。 它有時被稱做“鴨式辨型法”或“結(jié)構(gòu)性子類型化”。 在TypeScript里,接口的作用就是為這些類型命名和為你的代碼或第三方代碼定義契約。
interface Animal {
name: string,
readonly age: number, // 只讀屬性
sex?: number, // 可選屬性
}
const dog: Animal = {
name: 'dog',
age: 2,
}
dog.age = 3; // Cannot assign to 'age' because it is a read-only property.ts(2540)
六、函數(shù)
1.剩余參數(shù)
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
2.函數(shù)重載
函數(shù)重載或方法重載是使用相同名稱和不同參數(shù)數(shù)量或類型創(chuàng)建多個方法的一種能力。要解決前面遇到的問題,方法就是為同一個函數(shù)提供多個函數(shù)類型定義來進行函數(shù)重載,編譯器會根據(jù)這個列表去處理函數(shù)的調(diào)用。
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: any, b: any): any {
if (typeof a === "string" || typeof b === "string") {
return a.toString() + b.toString();
}
return a + b;
}
console.log(1, 2); // 3
console.log('1', '2'); //12
console.log('1', 2); //12
console.log(1, '2'); //12
為了讓編譯器能夠選擇正確的檢查類型,它與JavaScript里的處理流程相似。 它查找重載列表,嘗試使用第一個重載定義。 如果匹配的話就使用這個。 因此,在定義重載的時候,一定要把最精確的定義放在最前面。
注意,function add(a: any, b: any): any并不是重載列表的一部分,因此這里只有兩個重載:一個是接收對象另一個接收數(shù)字。 以其它參數(shù)調(diào)用 add會產(chǎn)生錯誤。
七、泛型
function identity(arg: number): number {
return arg;
}
function identity(arg: string): string {
return arg;
}
function identity(arg: any): any {
return arg;
}
使用any類型會導(dǎo)致這個函數(shù)可以接收任何類型的arg參數(shù),這樣就丟失了一些信息:傳入的類型與返回的類型應(yīng)該是相同的。如果我們傳入一個數(shù)字,我們只知道任何類型的值都有可能被返回。
因此,我們需要一種方法使返回值的類型與傳入?yún)?shù)的類型是相同的。 這里,我們使用了 類型變量,它是一種特殊的變量,只用于表示類型而不是值。
function identity<T>(arg: T): T {
return arg;
}
我們給identity添加了類型變量T。 T幫助我們捕獲用戶傳入的類型(比如:number),之后我們就可以使用這個類型。 之后我們再次使用了 T當做返回值類型?,F(xiàn)在我們可以知道參數(shù)類型與返回值類型是相同的了。 這允許我們跟蹤函數(shù)里使用的類型的信息。
我們把這個版本的identity函數(shù)叫做泛型,因為它可以適用于多個類型。 不同于使用 any,它不會丟失信息,像第一個例子那像保持準確性,傳入數(shù)值類型并返回數(shù)值類型。
八、聯(lián)合類型和交叉類型
聯(lián)合類型表示一個值可以是幾種類型之一。 我們用豎線( |)分隔每個類型,所以 number | string | boolean表示一個值可以是 number, string,或 boolean。
let a: string | number | boolean ;
交叉類型是將多個類型合并為一個類型。 這讓我們可以把現(xiàn)有的多種類型疊加到一起成為一種類型,它包含了所需的所有類型的特性。 例如, Person & Serializable & Loggable同時是 Person 和 Serializable 和 Loggable。 就是說這個類型的對象同時擁有了這三種類型的成員。
interface Company {
cid: number;
}
interface Employee {
age: number;
name: string;
}
type workerType = Company & Employee;
const wroker: workerType = {
cid: 1,
age: 2,
name: 'chen'
}
九、裝飾器
裝飾器(Decorator)是一種與類(class)相關(guān)的語法,用來注釋或修改類和類方法。
裝飾器是一種函數(shù),寫成@ + 函數(shù)名。它可以放在類和類方法的定義前面。
裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法, 訪問符,屬性或參數(shù)上。 裝飾器使用 @expression這種形式,expression求值后必須為一個函數(shù),它會在運行時被調(diào)用,被裝飾的聲明信息做為參數(shù)傳入。
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
上面代碼中,@testable就是一個裝飾器。它修改了MyTestableClass這個類的行為,為它加上了靜態(tài)屬性isTestable。testable函數(shù)的參數(shù)target是MyTestableClass類本身。
十、tsconfig.json
{
"compilerOptions": { //設(shè)置與編譯流程相關(guān)的選項。
"target": "es5", // 指定 ECMAScript 目標版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "commonjs", // 指定使用模塊: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"strict": true, // 啟用所有嚴格類型檢查選項
"noImplicitAny": true, // 在表達式和聲明上有隱含的 any類型時報錯
"strictNullChecks": true, // 啟用嚴格的 null 檢查
"suppressImplicitAnyIndexErrors": true,
"jsx": "preserve", // 指定 jsx 代碼的生成: 'preserve', 'react-native', or 'react'
"importHelpers": true, // 從 tslib 導(dǎo)入輔助工具函數(shù)
"moduleResolution": "node", // 決定如何處理模塊。或者是"Node"對于Node.js/io.js,或者是"Classic"(默認)。查看模塊解析了解詳情。
"experimentalDecorators": true, // 啟用實驗性的ES裝飾器。
"esModuleInterop": true,
"allowSyntheticDefaultImports": true, // module === "system" 或設(shè)置了 --esModuleInterop 且 module 不為 es2015 / esnext esModuleInterop 且 module 不為 es2015 / esnext 允許從沒有設(shè)置默認導(dǎo)出的模塊中默認導(dǎo)入。這并不影響代碼的輸出,僅為了類型檢查。
"strictPropertyInitialization": false, // 確保類的非undefined屬性已經(jīng)在構(gòu)造函數(shù)里初始化。若要令此選項生效,需要同時啟用--strictNullChecks。
"sourceMap": true, // 生成相應(yīng)的 .map文件。
"baseUrl": ".", // 用于解析非相對模塊名稱的基目錄
"noImplicitThis": false, // 當 this 表達式值為 any 類型的時候,生成一個錯誤
"types": [ // 要包含的類型聲明文件名列表。
"webpack-env"
],
"paths": { // 模塊名到基于 baseUrl的路徑映射的列表。
"@/*": [
"src/*"
]
},
"lib": [ // 指定要包含在編譯中的庫文件
"es6",
"es5",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [ // 設(shè)置需要進行編譯的文件,支持路徑模式匹配;
"src/**/*.ts",
"src/**/*.vue",
"node_modules/@types/node/globals.d.ts",
"node_modules/@types/node/globals.d.ts"
],
"exclude": [ // 設(shè)置無需進行編譯的文件,支持路徑模式匹配;
"node_modules"
]
}



