moon

moon

Build for builders on blockchain
github
twitter

TypeScript 類型系統詳解

ts-checker 是一個幫助你學習 TypeScript 從入門到精通系列,不僅包括了 ts 的基礎知識,還包括了 Type-Challenges 詳細題解。

數據類型#

基本數據類型#

  • 數值類型 number

    const age: number = 18
    
  • 字串類型 string

    const name: string = 'lybenson'
    
  • 布林類型 boolean

    const isMale: boolean = true
    
  • 空值 void: 常用在函數沒有返回值時

    function printHeight(height: number): void {
      console.log(height)
    }
    
  • nullundefined

  • any: 任何其他類型都是 any 的子類型,任何類型值都可以賦值給 any 類型的變數

    const anyUse: any = {
      name: 'lybenson'
    }
    anyUse.name
    
  • unknown: 未知類型,同 any 類型一樣,任何類型值也可以賦值給 unknown 類型的變數

    const unknownUse: unknown = {
      name: 'lybenson'
    }
    unknownUse.name // error: 'unknownUse' is of type 'unknown'.
    
  • never: 表示永不存在的值的類型

    function error(message: string): never {
      throw new Error(message)
    }
    

其他數據類型#

函數類型#

定義函數類型時需要提供參數類型和返回值類型

const sum = (a: number, b: number): number => {
  return a + b
}

返回值類型可不寫,ts 會自動進行類型推導

陣列類型#

陣列的類型聲明主要有下面兩種:

const arr1: number[] = []
const arr2: Array<number> = []

元組類型#

陣列一般由同種類型的值組成,但元組可以存儲不同類型的值

const student: [string, number] = ['lybenson', 18]

列舉類型#

用關鍵字 enum 聲明

enum Direction {
  NORTH,
  SOUTH,
  EAST,
  WEST
}

const direction: Direction = Direction.SOUTH

列舉值可以不寫,默認從 0 開始

聯合類型#

聯合類型表示變數的值為多種類型中的一種,強調,用 | 符號連接

type Roles = 'CEO' | 'CTO' | 'CFO'

const userRole: Roles = 'CTO'

交叉類型#

交叉類型表示變數有類型的所有屬性,強調,用 & 符號連接

type Student = {
  name: string
}
type Employee = {
  name: string
  salary: number
}
// UserRole 同時具有 Student 和 Employee 屬性
type UserRole = Student & Employee

const user: UserRole = {
  name: 'lybenson',
  salary: 3500
}

注意

被交叉的兩個類型具有相同的屬性名,但屬性類型不同时,則屬性類型也會進行交叉,如:

type Student = {
  name: number
}
type Employee = {
  name: string
  salary: number
}
// name 類型不同,則類型也會交叉
type UserRole = Student & Employee
// {
//   name: number & string
//   salary: number
// }

// 報錯: 不存在值同時具有 number 和 string 類型
const user: UserRole = {
  name: 'lybenson',
  salary: 3500
}

可選類型#

可選類型並不是一種具體的類型,而是一種類型泛式。

使用 ? 表示, 用來聲明變數類型或函數參數類型時指定一個類型,但不一定要求該變數或參數必須有值。本質是給原類型聯合 undefined 類型

function printName(firstName: string, lastName?: string) {
  if (lastName) {
    console.log(firstName + ' ' + lastName)
  } else {
    console.log(firstName)
  }
}
// lastName 為可選類型,可不傳
printName('lybenson')

// 自定義類型中定義可選屬性
type Employee = {
  name: string
  salary?: number
}
const emp: Employee = {
  name: 'lybenson'
}

-? 將屬性變為非可選。

只讀類型#

只讀類型同樣並不是一種具體的類型。

使用 readonly 表示屬性是只讀的,不可修改

// 定義 name 屬性是只讀的
type Employee = {
  readonly name: string
  salary?: number
}

const emp: Employee = {
  name: 'lybenson',
  salary: 3500
}

emp.name = 'jack ma' // Cannot assign to 'name' because it is a read-only property.

-readonly 將屬性變為非只讀。

自定義類型#

自定義類型常用 typeinterface, 兩者的區別是

  • type 定義聯合類型、交叉類型、元組類型、函數類型等。通常用於創建複雜的類型組合
  • interface 常用於定義對象類型的結構。可使用繼承等特性

type#

type User = {
  name: string
  age: number
  sex?: number
}

type Status = 'draft' | 'published'

interface#

interface User {
  name: string
  age: number
  sex?: number
  getName: () => string
}

注意

interface 定義的同名類型會自動合併,如:

interface User {
  name: string
}

interface User {
  age: number
}

// 自動合併後的類型是
interface User {
  name: string
  age: number
}

類型轉換#

as#

// 強制轉換為 any
const distance: number = '100000' as any

as const 將值視為不可變的常量,而不是可變的變數

const name = 'lybenson' as const

name 類型是 'lybenson', 而不是 string

如果是對象類型:

const user = {
  name: 'lybenson',
  age: 18
} as const

不使用 as const時,user 的類型會被推導為

const user: {
  name: string
  age: number
}

使用 as const 後,user 的類型會被推導為

const user: {
  readonly name: 'lybenson'
  readonly age: 18
}

<T>#

T 是需要轉換的類型

const distance: number = <any>'100000'

內置類型聲明#

內置類型可以幫助我們更方便的定義類型,例如 Omit 可以剔除對象的屬性

interface User = {
  name: string
  age: number
  sex?: number
  salary: number
  workTime: number
}

// Student 類型是 User 類型去除了字段 salary 和 workTime 後的類型
type Student = Omit<User, 'salary' | 'workTime'>

完整見下表

類型名說明
Partial<T>T 中所有屬性變為可選
Required<T>T 中所有屬性變為必選
Readonly<T>T 中所有屬性變為只讀
Pick<T, K extends keyof T>T 中選擇一組屬性,選擇的屬性在 K
Record<K extends keyof any, T>構造一個屬性名類型為 K, 屬性類型為 T 的對象類型。如type obj = Record<string, any>
Exclude<T, U>從聯合類型 T 中剔除包含在 U 中的類型
Extract<T, U>從聯合類型 T 中提取包含在 U 中的類型
Omit<T, K extends keyof any>T 中剔除在 K 中的屬性
NonNullable<T>從類型 T 中排除 nullundefined
Parameters<T extends (...args: any) => any>從函數類型 T 中提取參數類型,並返回一個由參數類型組成的元組類型
ReturnType<T extends (...args: any) => any>從函數類型 T 中提取並返回函數的返回值類型
InstanceType<T extends abstract new (...args: any) => any>從構造函數類型 T 中提取並返回構造函數實例的類型
Uppercase<S extends string>將字串類型 S 中的所有字符轉換為大寫字母,並返回一個新的字串類型
Lowercase<S extends string>將字串類型 S 中的所有字符轉換為小寫字母,並返回一個新的字串類型。
Capitalize<S extends string>將字串類型 S 的第一個字符轉換為大寫字母
Uncapitalize<S extends string>將字串類型 S 的第一個字符轉換為小寫字母
ThisType<T>指定方法中 this 關鍵字的類型
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。