Skip to content

TypeScript

项目常用类型整合

函数重载

ts
// 实现1
function add(x: string, y: string): string
function add(x: number, y: number): number {
  if (typeof x === 'string' && typeof y === 'string')
    return `${x},${y}`
  else
    return x + y
}

function add(x: string | number, y: string | number): string | number {
  return x + y
}
// 实现1
function add(x: string, y: string): string
function add(x: number, y: number): number {
  if (typeof x === 'string' && typeof y === 'string')
    return `${x},${y}`
  else
    return x + y
}

function add(x: string | number, y: string | number): string | number {
  return x + y
}

泛型

ts
function identity<T>(arg: T): T {
  return arg
}
function identity<T>(arg: T): T {
  return arg
}

类型映射

ts
interface Original { a: number, b: string }
type Modified = { [K in keyof Original]: Original[K] | null }
interface Original { a: number, b: string }
type Modified = { [K in keyof Original]: Original[K] | null }

条件类型

ts
type IsFunction<T> = T extends (...args: any[]) => any ? true : false
type IsFunction<T> = T extends (...args: any[]) => any ? true : false

递归类型

ts
interface TreeNode<T> {
  value: T
  children: TreeNode<T>[]
}
interface TreeNode<T> {
  value: T
  children: TreeNode<T>[]
}

组件声明

根目录 env.d.ts 文件

ts
/// <reference types="vite/client" />

// vue3 类型
declare module '*.vue' {
  import type { DefineComponent } from 'vue'

  const component: DefineComponent<object, object, any>
  export default component
}
// vite env 类型
interface ImportMetaEnv {
  YANG_APP_TITLE: string
  YANG_BASE_URL: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}
/// <reference types="vite/client" />

// vue3 类型
declare module '*.vue' {
  import type { DefineComponent } from 'vue'

  const component: DefineComponent<object, object, any>
  export default component
}
// vite env 类型
interface ImportMetaEnv {
  YANG_APP_TITLE: string
  YANG_BASE_URL: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

自定义类型

优先使用interface 实现不了用type

ts
interface Point {
  x: number
  y: number
}

interface Person {
  name: string
  age: number
}
interface Point {
  x: number
  y: number
}

interface Person {
  name: string
  age: number
}

联合类型和交叉类型

ts
// 联合类型
let result: string | number
// 交叉类型
type Person = { name: string } & { age: number }
// 联合类型
let result: string | number
// 交叉类型
type Person = { name: string } & { age: number }

infer 关键字

在TS中infer使用是指TypeScript中的infer关键字,它是用来声明类型推断变量的。使用infer关键字可以方便地从一个类型中提取出一个新的类型,这样就可以在类型中使用这个新的类型了。

ts
// 使用 infer 声明一个类型变量 U,用于解析 T 的类型

// ExtractSelf<T> 类型:如果 T 可以被赋值给 U,就返回 U,否则返回 T
type ExtractSelf<T> = T extends infer U ? U : T

type T1 = ExtractSelf<string> // string
type T2 = ExtractSelf<() => void> // () => void

// ExtractArrayItemType<T> 类型:如果 T 是一个数组类型,就返回数组元素的类型 U,否则返回 T
type ExtractArrayItemType<T> = T extends (infer U)[] ? U : T

type A1 = ExtractArrayItemType<Date[]> // Date
type A2 = ExtractArrayItemType<{ a: string }> // { a: string }

// ExtractReturnType<T> 类型:如果 T 是一个函数类型,就返回函数返回值的类型 U,否则返回 T
type ExtractReturnType<T> = T extends () => infer U ? U : T

type R1 = ExtractReturnType<() => number> // number
type R2 = ExtractReturnType<(a: number) => number[]> // number[]
// 使用 infer 声明一个类型变量 U,用于解析 T 的类型

// ExtractSelf<T> 类型:如果 T 可以被赋值给 U,就返回 U,否则返回 T
type ExtractSelf<T> = T extends infer U ? U : T

type T1 = ExtractSelf<string> // string
type T2 = ExtractSelf<() => void> // () => void

// ExtractArrayItemType<T> 类型:如果 T 是一个数组类型,就返回数组元素的类型 U,否则返回 T
type ExtractArrayItemType<T> = T extends (infer U)[] ? U : T

type A1 = ExtractArrayItemType<Date[]> // Date
type A2 = ExtractArrayItemType<{ a: string }> // { a: string }

// ExtractReturnType<T> 类型:如果 T 是一个函数类型,就返回函数返回值的类型 U,否则返回 T
type ExtractReturnType<T> = T extends () => infer U ? U : T

type R1 = ExtractReturnType<() => number> // number
type R2 = ExtractReturnType<(a: number) => number[]> // number[]

对象类型

ts
type Record<K extends keyof any, T> = {
  [P in K]: T;
}
type Record<K extends keyof any, T> = {
  [P in K]: T;
}