TypeScript 不能不知道的功能

TypeScript中好用且常用的功能介紹

Juo Penguin
6 min readAug 22, 2020

index索引

interface的交集、差集和聯集 — Omit, Pick, Partial, Record…

type的交集,差集 — Exclude, Extract

function常用搭配型別 — Parameters, ReturnType

TypeScript的 ”function” — Generic

為 “自訂的module” 建立型別檔 — index.d.ts

optional chain(v3.7+)

interface的交集、差集和聯集

Omit<Type, Keys>

只把keys去除掉,適合用於container(react)的情境

interface UserProps {
username: string
password: string
isAuth: boolean
}
type AuthedUserProps = Omit<UserProps, 'isAuth'>
//等同於
{
username: string
password: string
}

Pick<Type, Keys>

只拿Keys的property

interface PageProps {
title: string
content: string
}

type PagePreview = Pick<PageProps, 'title'>
//等同於
{
title: string
}

Patial<Type>

interface的每個property都變成optional,適合用於options之類的情境

interface SquareSpecs {
width: number | string
color: string
}
type SqurareSpecOptions = Partial<SquareSpecs>
//等同於
{
width?: number | string
color?: string
}

Record<Keys, Type>

構成一個由Keys組成的interface {[k in keyof Keys]: Type}

interface ThemeColors {
color: string
}
type TextKeys = 'title' | 'subtitle'
type TextColors = Record<TextKeys, ThemeColors>
//等同於
{
title: { color: string }
subtitle: { color: string }
}

type的交集,差集

Extract<Type, Union>: 交集

從type中只拿出想要的

type Width = number | string | (() => number | string)
type WidthStrType = Extract<Width, string>
// string

Exclude<Type, ExcludedUnion>: 差集

從type中拿掉不要的

type Width = number | string | (() => number | string)
type StaticWidth = Exclude<Width, Function>
// 等同於 number | string

function常用搭配型別

ReturnType<Type>

取得function的return 值的Type

declare function a(): {
b: string
}
type TypeA = ReturnType<typeof a>
// { b: string }
type TypeB = ReturnType<() => number>
// number

Parameters<Type>

取的function的參數Type

declare function b(width: string, specs: { color: string, }): anytype TypeA = Parameters<typeof b>
// [string, specs: { color: string }]
type TypeB = Parameters<(options: { a: string }) => any>
// [options: {a: string }]

Generic泛型: TypeScript的”function”

Type預留參數,型別的使用上更加靈活

// 基礎使用
function genArray<T>(params: T, length=1): T[] {
return [...Array(length)].map(() => params);
}
genArray(1);
// number[]
genArray([1, 2, 3], 10);
// number[][]
// 在type上使用
type Fn<P> = (params: P, objKey: string) => Record<string, P>
const fnA: Fn<number> = (params, objKey) => {
return {
[objKey]: params,
};
};
// 在interface使用
interface Specs<UnitType extends string | number> {
width: UnitType
height: UnitType
}
const specs: Specs<number> = {
// width: 0,
height: 0,
width: '0',
// error! Type 'string' is not assignable to type 'number'.
}

為 “自訂的module” 建立型別檔

index.d.ts

許多node module都會使用index.d.ts作為該module的type主要檔案,我們可以透過同樣的方法,為我們的專案也建立index.d.ts以方便整個專案的使用

  1. 在根目錄建立custom-types的資料夾(此資料夾名稱隨意),並修改tsconfig.json在typeRoots的設定中新增剛剛的資料夾
"compilerOptions": { 
"typeRoots": [//..., "./custom-types"]
}

2. 在custom-types資料夾中建立其他資料夾,此資料夾就是你”自訂的module”,並新增index.d.ts

./custom-types
./common-types
index.d.ts

3. 在index.d.ts中新增以下內容,讓TypeScript得知此為一個module

declare module "common-types" { 
type Hello = string
}

4. 完成後repo中的檔案就可以直接引用

// src/a.ts
import { Hello } from "common-types"

optional chain

TypeScript v3.7 新增的必用功能

// 原本寫法
a && a.b && a.b.c && a.b.c.d()
// 3.7之後
a?.b?.c?.d()

--

--