TypeScript

TypeScript 筆記 – 常見的 types

這篇來簡單筆記一下 TypeScript 中常用到的 types,以及常見的資料結構要怎麼用 type 來表示。

1. Primitives

1.1 string

const str: string = 'Hello World'

1.2 number

const num1: number = 24
const num2: number = 3.14

1.3 boolean

const bool: boolean = true

1.4 bigint

const oneHundred: bigint = BigInt(100)

1.5 symbol

  • Symbols are immutable, and unique.
let sym2 = Symbol("key")
let sym3 = Symbol("key")
sym2 === sym3
// false, symbols are unique
declare const sym1: unique symbol

class C {
  static readonly StaticSymbol: unique symbol = Symbol()
}

2. Arrays

2.1 Array

Array 用來表示一般常用的 array,基本上就是所有 element 的 type 都是一樣的

const arr1: number[] = [1, 2, 3]
const arr2: Array<number> = [4, 5, 6]

interface NumberArray {
  [index: number]: number
}
const arr3: NumberArray = [7, 8, 9]

2.2 ReadonlyArray

ReadonlyArray 用來表示這個 array 是 readonly 的,如果要 reassign 任何 element 都會噴錯

const weekDays: ReadonlyArray<string> = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']

weekDays[0] = 'Sunday'
// Error! Index signature in type 'readonly string[]' only permits reading.

2.3 Tuple

tuple 並不是一個 type,而是用來明確指定這個 array 有幾個 element 以及每個 element 的 type,因此 tuple 可以用來表示 element 中有不同 type 的 array

const pair: [number, string] = [123, 'world']

// 也可以用來表示有同樣 type element 的 array
const pair: [string, string] = ['hello', 'world']

tuple 可以允許 optional property

type Coord = [number, number, number?]

function setPosition(coord: Coord) {
  const [x, y, z] = coord
}

// const x: number
// const y: number
// const z: number | undefine

tuple 也可以和 rest operator 搭配使用

type StringNumberBooleans = [string, number, ...boolean[]]
// 第一個 element type 會是 string
// 第二個 element type 會是 number
// 剩下的 element type 會是 boolean

const a: StringNumberBooleans = ["hello", 1]
const b: StringNumberBooleans = ["beautiful", 2, true]
const c: StringNumberBooleans = ["world", 3, true, false, true, false, true]

type StringBooleansNumber = [string, ...boolean[], number]
// 第一個 element type 會是 string
// 中間的 element type 會是 boolean
// 最後一個 element type 會是 number

type BooleansStringNumber = [...boolean[], string, number]
// 倒數第二個以前的 element type 會是 boolean
// 倒數第二個 element type 會是 string
// 最後一個 element type 會是 number

2.4 readonly tuple

在 tuple 前面加上 readonly,會讓這個 tuple 不能 reassign 任何 element

const pair: readonly [string, number] = ['Hello', 123]
pair[0] = 'world'
// Error! Cannot assign to '0' because it is a read-only property.

也可以用 as const 來表示:

const pair = ['Hello', 123] as const
pair[0] = 'world'
// Error! Cannot assign to '0' because it is a read-only property.

3. Functions

3.1 function 內部的 type

  • Parameter Type Annotations

用來標示 parameter 的 type

function greet(name: string) {
  console.log("Hello, " + name.toUpperCase() + "!!");
}

greet(42);
Argument of type 'number' is not assignable to parameter of type 'string'.
  • Return Type Annotations

用來標示 function return value 的 type

function getFavoriteNumber(): number {
  return 26;
}

// functions which return promises
async function getFavoriteNumber(): Promise<number> {
  return 26;
}

3.2 Type Alias

通常用 Function Type Expressions 的方式來表示,語法類似 arrow function

type GreetFunction = (a: string) => void

function greeter(fn: GreetFunction) {
  fn("Hello, World")
}
 
function printToConsole(s: string) {
  console.log(s)
}
 
greeter(printToConsole)

3.3 interface

當 function 上有其他 property 時,我們可以用物件的方式 (interface 或 type alias) 來表示

interface DescribableFunction {
  description: string
  (someArg: number): boolean
}
function doSomething(fn: DescribableFunction) {
  console.log(fn.description + " returned " + fn(6))
}

function myFunc(someArg: number) {
  return someArg > 3
}
myFunc.description = "default description"

doSomething(myFunc)

3.4 Generic Functions

有時候 function 不會知道 parameter 會以什麼 type 傳進來,這時候可以用 generic 來將 type 作為變數傳進 function

function firstElement<T>(arr: T[]): T | undefined {
  return arr[0]
}

console.log(firstElement([1, 2, 3]))

4. Object Types

4.1 Type Alias

type alias 有點像是將 type 作為變數重複使用,因此也可以用來表示 object 的 type

type User = {
  name: string
  age: number
  isAdult: boolean
}

const user: User = {
  name: 'Jimmy',
  age: 20,
  isAdult: true
}

const getUserName = (user: User) => {
  return user.name
}

4.2 Interface

interface 也可以用來表示 object 的 type,和 type alias 的語法很類似,差別在於不需要 =

interface User {
  name: string
  age: number
  isAdult: boolean
}

const user: User = {
  name: 'Jimmy',
  age: 20,
  isAdult: true
}

const getUserName = (user: User) => {
  return user.name
}

4.3 Object 內部

const obj1: { name: string, age: number } = { name: 'Jimmy' }
// Property 'age' is missing in type '{ name: string; }' but required in type '{ name: string; age: number; }'

const obj2: { name: string, age: number } = { name: 'Jimmy', age: 20 }
// ok
  • Optional Properties
    • 在 property name 後加上 ? ,代表這個 property 對這個 object 來說,是 optional 的
const obj1: { name: string, age?: number } = { name: 'Jimmy' }
  • readonly Properties
    • 在 property 前面加上 readonly 這個 keyword,用來表示這個 property 不能更改
interface User {
  readonly name: string
  age: number
  isAdult: boolean
}

const user: User = {
  name: 'Jimmy',
  age: 20,
  isAdult: true
}

user.name = 'Jack'
// Error! Cannot assign to 'name' because it is a read-only property.
  • index signatures
    • 用來表示 key value 的 type,不過 js 的 object key 都會被轉成 string,所以通常 key 的部分都會是 string,如果是 number 的話,通常是用來表示 array
interface User {
  age: number
  [index: string]: number
}

const user: User = {
  age: 20,
  name: 'Jimmy'
  // Error! Type 'string' is not assignable to type 'number'.ts(2322)
  // object.ts(3, 3): The expected type comes from this index signature.
}

// 用來表示 array
interface StringArray {
  [index: number]: string
}

const classmates: StringArray = ['Jimmy', 'Jack']

5. 參考資料

Documentation – Everyday Types
Documentation – More on Functions
Documentation – Object Types

如果覺得我的文章有幫助的話,歡迎幫我的粉專按讚哦~謝謝你!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top