TS 最佳实践笔记
前言
用 TS 总能引起我强烈的代码洁癖不适感,可能还没摸透这个的使用姿势吧,每次用一个新特性的时候,都纠结半天怎么用最合适,网上也很少能找到答案。于是摸爬滚打了一波后觉得还是记录一下吧,如果有更好的使用方式,欢迎来交流,随时虚心学习。
纯 TS 实践案例
1. 处理接口枚举
场景
接口响应值是数字枚举类型,前端页面需要用中文展示对应的枚举。
解决方案
// 定义接口枚举
export enum StatusEnum {
/** 待审核 */
TODO = 10,
/** 已过审 */
DONE = 20,
/** 未过审 */
NONE = 30,
}
// 定义文中展示需要显示的文字
export const statusCn = {
[StatusEnum.TODO]: '待审核',
[StatusEnum.DONE]: '已过审',
[StatusEnum.NONE]: '未过审',
}
优势
- 保持只定义一份和后端同步的枚举值,方便后期维护。
2. 定义接口数据类型
方案
协商一下让后端在接口文档中标明响应值字段可能不返回或可能返回null的字段。据此定义接口字段是否必传即可。
export interface ListItemType {
/** id */
id: number;
/** 标题 */
title: string;
/** 适用城市 */
cities?: CityItemType[];
/** 创建时间 */
time: string;
/** 当前状态 */
status: StatusEnum;
/** 各项统计数据 */
statistics?: StatisticsType;
}
优势
- 初始化储存接口数据的变量时没必要所有字段都给初始值
- 对象类型或数组类型,会在页面使用的地方提示你应该做兼容处理
3. 回调函数的参数怎样定义才可以拥有类型推断?
场景
// -----文件1:函数定义-----
export interface ObjType {
name: string;
age: number;
}
export interface CBType {
(obj: ObjType): void
}
interface propsType {
callback: CBType
export function fn({callback}: propsType) {
callback({name: '张三',age: 12});
}
// -----文件2:函数调用-----
import { fn } from './文件1';
// inline 方式调用
fn({callback: (obj) => {
// 这里可以使用 obj 类型推断
}})
// 外部定义的回调函数调用
const fnCB = (obj) => {
// obj 为隐式 any 类型,无法使用类型推断
}
fn({callback: fnCB});
解决方案
- 函数定义的文件暴露出回调函数的签名即 CBType 供其他文件调用时直接给回调函数使用。
- 暴露出回调函数参数的类型定义即 ObjType 供其他文件调用时给回调函数参数使用(antd 目前是这种方案)。
- 利用 ts 类型推断定义回调函数,代码如下。问题:组件回调函数没想好怎么定义呢。
const fnCB: Parameters<typeof fn>[0]['callback'] = (obj) => {
// 可以使用 obj 的类型推断
}