文章目錄
- TypeScript 是什麼
- TypeScript基本使用
-
- 安裝編譯 TS 的工具包
- 運作編譯TS
- 簡化TS運作步驟
- TypeScript 常用類型
-
- 類型注解
- 常用基礎類型
-
- JS 已有類型
-
- 原始類型
- 對象類型
-
- 數組類型
- 函數類型
- 對象類型
- TS 新增類型
-
- 聯合類型
- 類型别名
- 接口
- 元組(Tuple)
- 類型推論
- 類型斷言
- 字面量類型
- 枚舉類型
- any類型
- TS中的typeof運算符
TypeScript 是什麼
(簡稱:
TypeScript
)是 JavaScript 的
TS
(JS 有的 TS 都有)。
超集
(在 JS 基礎之上,為 JS 添加了類型支援)。
TypeScript = Type + JavaScript
是微軟開發的開源程式設計語言,可以在任何運作
TypeScript
的地方運作。
JavaScript
-
屬于靜态類型的程式設計語言,TypeScript
屬于動态類型的程式設計語言。JS
- 靜态類型:編譯期做類型檢查。
- 動态類型:執行期做類型檢查。
- 代碼編譯和代碼執行的順序:1 編譯 2 執行。簡單來說
可以提前到在編寫代碼的同時就發現代碼中的錯誤,減少找 Bug、改 Bug 時間TS
TypeScript基本使用
安裝編譯 TS 的工具包
Node.js/浏覽器,隻認識代碼,不認識
JS
代碼。需要先将
TS
代碼轉化為
TS
代碼,然後才能運作。
JS
- 安裝指令:
npm i -g typescript
-
包:用來編譯 TS 代碼的包,提供了typescript
指令,實作了tsc
TS -> JS
的轉化。
驗證是否安裝成功(檢視 typescript 的版本):
tsc –v
運作編譯TS
- 建立 hello.ts 檔案(注意:TS 檔案的字尾名為
)。.ts
- 将 TS 編譯為 JS:在終端中輸入指令,
(此時,在同級目錄中會出現一個同名的 JS 檔案)。tsc hello.ts
- 執行 JS 代碼:在終端中輸入指令,
。node hello.js
簡化TS運作步驟
簡化方式: 使用
ts-node
包,直接在 Node.js 中執行 TS 代碼。
安裝指令:(ts-node 包提供了 ts-node 指令)
npm install -D tslib @types/node
使用方式:
ts-node hello.ts
解釋:
ts-node
指令在内部偷偷的将 TS -> JS,然後,再運作 JS 代碼。
TypeScript 常用類型
類型注解
說明:代碼中的
: number
就是類型注解。
作用:為變量添加類型限制。比如,上述代碼中,約定變量 age 的類型為
number
(數值類型)。
解釋:約定了什麼類型,就隻能給變量指派該類型的值,否則,就會報錯。
常用基礎類型
JS 已有類型
原始類型
number
string
boolean
null
undefined
symbol
let age: number = 18
let personName: string = '張三'
let bol: boolean = false
let test: null = undefined
let test1: null = null
let test2: undefined = undefined
let test3: undefined = null
let test4: symbol = Symbol()
對象類型
- 對象類型:
object
(包括,數組、對象、函數等對象)。
特點:對象類型,在 TS 中更加細化,每個具體的對象都有自己的類型文法。
數組類型
- 兩種寫法:(推薦使用
寫法)number[]
let numbers: number[] = [1, 2, 3]
let numbers2: Array<number> = [1, 2, 3]
let strings: string[] = ['1', '2']
let strings2: Array<string> = ['1','2']
函數類型
函數的類型實際上指的是:和
函數參數
的類型
傳回值
- 兩種方式
- 單獨指定參數,傳回值的類型
function add (num1: number, num2:number):number {
return num1 + num2
}
const add1 = (num1:number, num2:number): number => {
return num1 + num2
}
- 同時指定參數,傳回值的類型
可以通過類似箭頭函數形式的文法來為函數添加類型
注意:這種形式隻适用于函數表達式
// 同時指定參數,傳回值類型
const add: (num1: number, num2: number) => number = (num1, num2) => {
return num1 + num2
}
- 可選參數
在可傳可不傳參數後面添加 ?
注意:可選參數隻能出現在參數清單的最後,也就是說在
可選參數後面不能再出現必選參數
(TS有提示)
function mySlice(start?: number, end?: number): void {
console.log('開始索引', start, '結束索引', end)
}
對象類型
TS 中對象的類型就是在描述對象的結構。
let person: {
name: string;
age: number;
sayHi(): void
sayHi1: () => void
} = {
name: '張三',
age: 18,
sayHi(){
console.log('hello world')
},
sayHi1: () => {}
}
- 可選屬性
可選屬性的文法與函數可選參數的文法一緻,都使用 ?
(問号)來表示。
// axios({...})的get請求可以省略method
function myAxios(config:{
url: string;
methods?: string
}) {
console.log(config)
}
TS 新增類型
聯合類型
自定義類型(類型别名)
接口
元組
字面量類型
枚舉
void
any
等。
聯合類型
let arr: (number | string) [] = [1, 2, 'a']
解釋:
|
(豎線)在 TS 中叫做聯合類型(由兩個或多個其他類型組成的類型,表示可以是這些類型中的任意一種)。
類型别名
類型别名(自定義類型):為任意類型起别名
當同一類型(複雜)被多次使用時,可以通過類型别名,簡化該類型的使用
- 使用
關鍵字來建立類型别名。type
- 類型别名(比如,此處的
),可以是任意合法的變量名稱。CustomArray
- 建立類型别名後,直接使用該類型别名作為變量的類型注解即可。
type customArry = (number | string) []
let arr1: customArry = [1, 2, 'a', 'b']
接口
一個對象類型被多次使用時,一般會使用 接口(interface
)來描述對象的類型,達到複用的目的
- 使用
關鍵字來聲明接口interface
- 接口名稱可以是任意合法的變量名稱
- 聲明接口後直接使用接口名稱作為變量的類型(與類型别名相似)
- 因為每一行隻有一個屬性類型,是以屬性類型後沒有
分号;
interface Person {
name: string
age: number
sayHi: () => void
}
let person1: Person = {
name: '張三',
age: 18,
sayHi: () => {
console.log('helllo TS')
}
}
- 與type(類型别名)比較
- 相同點
- 都可以給對象指定類型
- 不同點
- 接口: 隻能為對象指定類型
- 類型别名:可以為任意類型指定别名
- 相同點
- extends(繼承)
如果兩個接口之間有相同的屬性或方法,可以将公共的屬性或方法抽離出來,通過 繼承來實作複用。
// interface Point2D {x: number; y: number}
// interface Point3D {x: number; y: number; z: number}
// 使用繼承
interface Point2D {x: number; y: number}
interface Point3D extends Point2D {z : number}
let point: Point3D = {
x: 1,
y: 2,
z: 3
}
- 使用
關鍵字實作了接口 Point3D 繼承 Point2D。extends(繼承)
- 繼承後,Point3D 就有了 Point2D 的所有屬性和方法(此時,Point3D 同時有 x、y、z 三個屬性)。
元組(Tuple)
元組類型是另一種類型的數組, 它确切地知道包含多少個元素,以及特定索引對應的類型
。
// 地圖中使用經緯度
// 使用數組(可以出現任意多個數字)
let position: number[] = [123.00, 100.10]
// 使用元組(對應個數,更為嚴謹)
let dot: [number, number] = [100.00, 100.00]
類型推論
在 TS 中,某些沒有明确指出類型的地方,TS 的類型推論機制會幫助提供類型。
- 聲明變量并初始化時
- 決定還是傳回值時
注意:這兩種情況下,類型注解可以省略不寫! 推薦:能省略類型注解的地方就省略(偷懶,充分利用TS類型推論的能力,提升開發效率)。
類型斷言
- 使用場景
- 有時候你會比 TS 更加明确一個值的類型,此時,可以使用類型斷言來指定更具體的類型。
注意:getElementById 方法傳回值的類型是 HTMLElement,該類型隻包含所有标簽公共的屬性或方法,不包含 a标簽特有的 href 等屬性。
是以,這個類型太寬泛(不具體),無法操作
href
等 a 标簽特有的屬性或方法。
解決方式:這種情況下就需要使用類型斷言指定更加具體的類型。
技巧:在浏覽器控制台,通過
console.dir()
列印 DOM 元素,在屬性清單的最後面,即可看到該元素的類型
- 兩種寫法
- 使用
關鍵字實作類型斷言as
const aLink1 = document.getElementById('result_logo') as HTMLAnchorElement
- 使用
文法<>
字面量類型
let str = 'hello string'
const str1 = 'hello ts'
此處的
hello ts
就是
字面量類型
,str是一個變量,它的值可以是任意字元串,是以類型為
string
,str1是一個常量它的值隻能是
'hello ts'
,是以它的類型為
'hello ts'
,也就是說
某個特定的字元串也可以作為TS中的類型
,除字元串外,任意JS字面量(對象、數字等)都可以作為類型使用。
- 字面量類型使用場景
字面量類型配合聯合類型一起使用。用來表示一組明确的可選值清單。
function change (direction: 'up' | 'down' | 'left' | 'right') {
console.log(direction)
}
解釋:參數 direction 的值隻能是 up/down/left/right 中的任意一個。
優勢:相比于 string 類型,使用字面量類型更加精确、嚴謹。
枚舉類型
- 定義:
- 枚舉的功能類似于字面量類型+聯合類型組合的功能,也可以表示
。一組明确的可選值
-
。它描述一個值,該值可以是這些命名常量中的一個。枚舉:定義一組命名常量
- 枚舉的功能類似于字面量類型+聯合類型組合的功能,也可以表示
- 使用
- 使用 enum 關鍵字定義枚舉。
- 約定枚舉名稱、枚舉中的值以大寫字母開頭。
- 枚舉中的多個值之間通過 ,(逗号)分隔。
- 定義好枚舉後,直接使用枚舉名稱作為類型注解。
enum Direction {Up, Down, Left, right}
let str3: Direction = Direction.Up
function changeEnum (val: Direction) {
console.log(val)
}
changeEnum(Direction.Down)
// 1
- 特點
- 類似于 JS 中的對象,直接通過點
文法通路枚舉的成員。(.)
- 枚舉成員是有值的,預設為:
從 0 開始自增的數值
- 也可以給枚舉中的成員初始化值
- 枚舉成員的值為數字的枚舉,稱為:
。數字枚舉
-
:枚舉成員的值是字元串。(字元串枚舉沒有自增長行為,是以,字元串枚舉的每個成員必須有初始值。)字元串枚舉
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
- 枚舉是 TS 為數不多的非 JavaScript 類型級擴充(不僅僅是類型)的特性之一。
- 其他的類型會在編譯為 JS 代碼時自動移除。但是,枚舉類型會被編譯為 JS 代碼!
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
編譯後
var Direction;
(function (Direction) {
Direction["Up"] = "Up";
Direction["Down"] = "Down";
Direction["Left"] = "Left";
Direction["Right"] = "Right";
})(Direction || (Direction = {}));
說明:枚舉與前面講到的字面量類型+聯合類型組合的功能類似,都用來表示一組明确的可選值清單。
一般情況下,推薦使用
字面量類型+聯合類型組合的方式
,因為相比枚舉,這種方式更加直覺、簡潔、高效。
any類型
不推薦使用 any!這會讓 TypeScript 變為 “AnyScript”(失去 TS 類型保護的優勢)
- 當值的類型為 any 時,可以對該值進行任意操作,并且不會有代碼提示。
let obj: any = 'sdad'
let strw: any = {}
obj()
//以上操作都不會有任何類型錯誤提示,即使可能存在錯誤!
- 其他隐式具有 any 類型的情況:
- 聲明變量不提供類型也不提供預設值
- 函數參數不加類型
注意:因為不推薦使用 any,是以,這兩種情況下都應該提供類型!
TS中的typeof運算符
- JS中的typeof操作符
console.log(typeof 'Hello')
// string
- TS 也提供了
操作符:可以在類型上下文中引用變量或屬性的類型(類型查詢)。typeof
- 使用場景::根據已有變量的值,擷取該值的類型,來簡化類型書寫。
let p = {a: 1, b: 2}
function fun(pre: typeof p) {} // =>等價于 fun({a: number, b:number})
fun({a: 2, b: 5})
1.
typeof
出現在類型注解的位置(參數名稱的冒号後面)所處的環境就在
類型上下文
(差別于 JS 代碼)。
2. 注意:
typeof
隻能用來查詢變量或屬性的類型,無法查詢其他形式的類型(比如,函數調用的類型)。