Typescript utilitytypes的使用,part 1

2021年1月3日 ... ☕️ 2 min read

在日常工作时,处理业务上的数据,很多时候接口返回数据,在用TS定义时,都有繁琐且重复的问题。这些数据结构通常都很简单:用字符串作为key,然后字符串作为value,以此为基础对象,扩展成数组或复杂对象。

Record就可以专门用来检查这种结构的对象。

比如:

result = {
  status: 'success',
  data: {
    id: '1313243',
    title: 'Some title',
    createTime: '2021-01-03 13:30:00'
  },
  message: 'OK'
};

为了适配这种格式,我们有必要写个type或者interface,来在其他地方做类型限定。status和message都好说,但是到data的时候,嗯……直接用any吗?

interface IResult {
  status: string;
  message: string;
  data: any;
}

然后除去老师傅告诉你的any弊端,最棘手的是,IDE报警告(错误)了。

我之前一般老老实实写一堆data的数据来匹配结果,或者掩耳盗铃,ignore next line…但是有没有其他办法呢?

直到我最近看文档发现辅助类型这一章,恍然大悟。

interface IResult {
  status: string;
  message: string;
  data: Record<string, string>;
}

这样,即可保证data里的数据是个对象,且key和value均为string。

进一步的操作,可以限定为具体某个对象的key。例如:

type PostType = {
  id: string;
  title: string;
  createTime: string;
}

interface IResult {
  status: string;
  message: string;
  data: Record<keyof PostType, string>;
}
// 定义
const res: IResult = {
  status: 'success',
  data: {
    id: '1313243',
    title: 'Some title',
    createTime: '2021-01-03 13:30:00'
  },
  message: 'OK'
};

2、key不固定的对象类型

比如接口返回了以随机ID为key的对象

{
  '0ea32fdh': {title: 'some title 1', comments: 12},
  '0ea33fdh': {title: 'some title 2', comments: 24},
  '0ea34fdh': {title: 'some title 3', comments: 36},
}

如何定义呢?

type PostType = {
  title: string;
  comment: number;
}
interface IResult {
  [k: string]: PostType;
}

或者用Record

type PostContentType = {
  title: string;
  comments: number;
}

type IPostType = Record<string, PostContentType>;

const post: IPostType = {
  '0ea32fdh': {title: 'some title 1', comments: 12},
  '0ea33fdh': {title: 'some title 2', comments: 24},
  '0ea34fdh': {title: 'some title 3', comments: 36},
}

相对于前一种,使用Record没有使用强制转换,本身看起来也更易读。

#TypeScript

SideEffect is a blog for front-end web development.
Code by Axiu / rss