Skip to content

风格指南

减少重复代码

js
interface Person {
  firstName: string;
  lastName: string;
}

interface PersonWithBirthDate {
  firstName: string;
  lastName: string;
  birth: Date;
}

方案

  1. extends
  2. 交叉运算符 &
js
interface Person {
  firstName: string;
  lastName: string;
}

interface PersonWithBirthDate extends Person {
  birth: Date;
}

type PersonWithBirthDate = Person & { birth: Date }

定义类型匹配初始化对象

js
const INIT_OPTIONS = {
  width: 640,
  height: 480,
  color: '#00FF00',
  label: 'VGA'
}

interface Options {
  width: number;
  height: number;
  color: string;
  label: string;
}

// opt
type Options = typeof INIT_OPTIONS

更精确的类型

js
interface Album {
  artist: string; // 艺术家
  title: string; // 专辑标题
  releaseDate: string; // 发行日期:YYYY-MM-DD
  recordingType: string; // 录制类型:"live" 或 "studio"
}

// recordingType: "live" | "studio";

类型总是有效状态

js
interface State {
  pageContent: string;
  isLoading: boolean;
  errorMsg?: string;
}
js
function renderPage(state: State) {
  if (state.errorMsg) {
    return `呜呜呜,加载页面出现异常了...${state.errorMsg}`
  } else if (state.isLoading) {
    return `页面加载中~~~`
  }
  return `<div>${state.pageContent}</div>`
}

// 输出结果:页面加载中~~~
console.log(renderPage({ isLoading: true, pageContent: '' }))
// 输出结果:<div>大家好</div>
console.log(renderPage({ isLoading: false, pageContent: '大家好呀' }))
js
async function changePage(state: State, newPage: string) {
  state.isLoading = true
  try {
    const response = await fetch(getUrlForPage(newPage))
    if (!response.ok) {
      throw new Error(`Unable to load ${newPage}: ${response.statusText}`)
    }
    const text = await response.text()
    state.isLoading = false
    state.pageContent = text
  } catch (e) {
    state.errorMsg = '' + e
  }
}

存在问题

  • 在 catch 语句中,未把 loading 设为 false
  • 未清理 errorMsg
js
interface RequestPending {
  state: 'pending';
}

interface RequestError {
  state: 'error';
  errorMsg: string;
}

interface RequestSuccess {
  state: 'ok';
  pageContent: string;
}

type RequestState = RequestPending | RequestError | RequestSuccess
js
function renderPage(state: State) {
  const { currentPage } = state
  const requestState = state.requests[currentPage]
  switch (requestState.state) {
    case 'pending':
      return `页面加载中~~~`
    case 'error':
      return `呜呜呜,加载第${currentPage}页出现异常了...${requestState.errorMsg}`
    case 'ok':
      ;`<div>第${currentPage}页的内容:${requestState.pageContent}</div>`
  }
}
js
async function changePage(state: State, newPage: string) {
  state.requests[newPage] = { state: 'pending' }
  state.currentPage = newPage
  try {
    const response = await fetch(getUrlForPage(newPage))
    if (!response.ok) {
      throw new Error(`无法正常加载页面 ${newPage}: ${response.statusText}`)
    }
    const pageContent = await response.text()
    state.requests[newPage] = { state: 'ok', pageContent }
  } catch (e) {
    state.requests[newPage] = { state: 'error', errorMsg: '' + e }
  }
}