gnosis23 / hello-world-blog

还是 issues 里面写文章方便
https://bohao.work
0 stars 0 forks source link

TypeScript类型编程 #108

Open gnosis23 opened 2 years ago

gnosis23 commented 2 years ago

高级类型

也就是类型编程:对类型进行操作能写出更好的类型,从而使得代码更加安全

一些资源

gnosis23 commented 2 years ago

挪到了一个单独仓库里:https://github.com/gnosis23/type-challenge-solutions

gnosis23 commented 2 years ago

用TypeScript收窄类型约束

例1:约束函数参数

比如有个用来播放歌曲的函数,参数为歌曲名称。

如果是用 JS 写的,那么这个 song 的约束就可以传任意字符串,就有可能会出错

const songs = ["song1", "song2", "hello"];

function playSong(song) {
  // doSomething
}

而使用 TS 就能对这个参数进行约束,这样一旦输入其他歌名就会编译错误。

// 加上 as const 是为了让 TS 推导出更具体的类型,而不是string[]
const songs = ["song1", "song2", "hello"] as const;

function playSong(song: typeof songs[number]) {
  // doSomething
}

例2:更具体的返回参数

假设有个函数的输入是地址字符串(形如Name,Date,Address),输出的是切割好的信息,那么在 JS 里面是这样的

function getAddress(str) {
  return { 
      name: str.split(",")[0],
      date: str.split(",")[1],
      address: str.split(",")[2]
  }
}

getAddress("wang,2022,Shanghai")

这样返回的类型就完全丢了,只有比较宽泛的类型,如 name = string。

而用 TS 可以做得更好,直接就能在编辑器里看到具体对应的函数类型

function getAddress<Name extends string, Date extends string, Address extends string>(
  str: `${Name},${Date},${Address}`
) {
  // validate string etc
  return { 
      name: str.split(",")[0] as Name,
      date: str.split(",")[1] as Date,
      address: str.split(",")[2] as Address
  }
}

const address = getAddress("wang,2022,Shanghai")
address.name // 'wang'

例3:巧用类型推导

用函数中的范型参数,可以得到更灵结果

function getBowl<T>(items: T): { items: T } {
  return { items }
}