TS相關
基本概念
型別註解:ts裡的型別註解是一種輕量級的為函式或變數新增約束的方式
基礎型別
布林值、數字、字串、陣列、元組、列舉、any、void、null、undefined、never、object
any、unknown、never、void
定義
- any:任意型別的變數
- unknown:表示未知型別
- never:永不存在的值的型別
- void:無任何型別,沒有型別
unknown與any類似,但使用前必須進行斷言或守衛,從型別推導來講,unknown是最高階型別,any是unknown的下一級
nerver、void用於函式時,never表示函式用於執行不到返回值那一步(丟擲異常或死迴圈)的返回值型別,即用不存在的值的型別,而void則表示沒有返回值,不返回或返回undefined。從型別推導來講,never是最低層,void與any同級
使用
- 能不使用any就不用
- 宣告時如果不確定具體的型別,則可以使用unknown代替,在使用時用型別斷言或型別守衛進行型別收縮
- never常用於構造條件型別來組合出更靈活的型別定義
- void常用於表示型別沒有返回值
擴充套件
any與unknown
在原先的typescript中,any屬於top type(最高階型別),在typescript3.0中,unknown才是top type
如果不縮小型別,就無法對unknown型別執行任何操作
ts高階用法
- 介面(interface)可以描述一個物件或者函式
- 類(class)
- 函式
- 泛型
- 列舉
- 迭代器和生成器
- 裝飾器
- 繼承、多型、過載、重寫
- 抽象類&抽象方法
具體使用示例可以看官網
TS編譯原理
graph LR
原始碼 --> 掃描器(scanner) --> Token流(中間產物) --> 解析器(parser) --> AST
AST --> 檢查器(checker) --> 型別檢查功能
AST --> 繫結器(binder) --> symbois(符號) -.- 檢查器(checker) -.- 發射器
AST --> 發射器(emitter) --> javascript程式碼
實線為主流程,有三條,虛線為獨立流程,符號單獨指向了檢查器,檢查器單獨指向了發射器
總的來說是
token流和ast類似,是掃描之後轉換程式碼的一箇中間產物,也是一個物件,不過key和value不一樣,但是總體構成是類似的
型別推論圖
面試題
- 以下程式碼ts推論出來的型別是什麼
let a = 1024 // number
let b = '1024' // string
const c = 'apple' // null,const型別推論出來的都是null
let d = [true, false, true] // array,準確來說是boolean[]
let e = {name: 'apple'} // object
let f = null // null
- 可賦值性
子集可以賦值給超集,超集不能賦值給子集,除非做出斷言
function a(input: string): string {
return input
}
function b(iniput: string | number) {
return input
}
// a可以直接賦值給b
let input = a()
b(input)
// 斷言方法1:as關鍵字
let input = b()
a(input as string)
// 斷言方法2:透過泛型固定引數型別
a(<string>input)
type與interface異同
在官方文件裡,描述type的作用是為型別起別名,interface則是側重描述資料結構的(比如一個物件裡包含了什麼屬性)
用法
- type
type age = number
type dataType = number | string
type method = 'GET' | 'POST' | 'PUT' | 'DELETE'
type User = {
name: string
age: number
}
// 合併type
type name = {
name: string
}
type User = name & {age: string}
- interface
interface User {
name: string
age: number
}
// 合併interface
interface Admin extends User {
id: number
}
// interface 也可以合併type
type User = {
name: string
age: number
}
interface Admin extends User {
id: number
}
共同點
- 都可以描述一個物件或函式
- interface和type都可以互相擴充,語法上不同,interface使用
extends
關鍵字,type是用&
符號
不同點
- type可以用於其他型別(聯合型別、元組型別、基本型別(原始值)),interface不支援
type PointX = {x: number}
type PointY = {y: number}
//聯合
type Point = PointX | PointY
// 元組
type Data = [PointX, PointY]
// 原始值
type Name = Number
// typeof的返回值
let div = document.createElement('div')
type B = typeof div
- interface可以多次定義,並自動合併所有成員變數,type不支援
- type能使用in關鍵字生成對映型別,interface不支援
type Keys = 'firstname' | 'surname'
type DudeType = {
[key in Keys]: string
}
// 等同於
type DudeType = {
firstname: string
surname: string
}
裝飾器問題
執行順序
- 有多個引數裝飾器時,從最後一個引數依次向前執行,也就是說裝飾器執行順序是倒序的
- 方法和方法引數中引數裝飾器先執行
- 類裝飾器總是最後執行
- 方法和屬性裝飾器,誰在前面誰先執行,因為引數是屬於方法一部分,所以引數會一直緊緊挨著方法執行
介面型別
- 屬性類介面
- 函式類介面
- 可索引介面
- 類型別介面
- 擴充套件介面