typescript 在业务的使用,更加聚焦业务开发本身。如:用户登录,数据列表,详情页面,安全信息,分析图表,按照数据类型抽象出来,我们一起试着写一写。假设你已经掌握了类型运算的知识,如果没有,可以看上一篇typescript 深化学习,类型运算的原始动力。让我们开始吧...
原始类型
const isLogin: boolean = false;
const price: number = 1;
const userName: string = "Lucy";
// 唯一标识符
const unique: symbol = Symbol("unique");
对象类型
/**
* 登录可能分为多种渠道:微信,微博,账号登录,手机登录
* 为简单起见,只分2种,LoginReqByAccount 或者 LoginReqParamsByOther
*/
type LoginType = "account" | "other";
// 账号方式登录请求参数
interface LoginReqByAccount {
name: string;
password: string;
phone: number;
// 登录类型
type: LoginType;
keepPwd?: boolean;
}
// 其它方式登录的请求参数
interface LoginReqParamsByOther {
id: number;
// 签名
sign: string;
// 登录类型
type: LoginType;
}
// 登录的请求参数
type LoginParams = LoginReqByAccount | LoginReqParamsByOther;
// 后台返回的业务数据
type ResBusinessData = {
userId: number;
// 用户名
name: string;
// 昵称,不一定有,可选
nickName?: string;
// 会员级别
level: number;
// 其它属性
[p: string]: unknown;
} | null;
interface LoginResponse {
code: number;
// 成功错误信息的描述
message: string;
// 业务数据
data: ResBusinessData;
}
// 分页
interface Pagination<T extends number = number> {
current: T;
pageSize: T;
}
// 定义一个状态的map对象,以表示不同状态icon
const StatusMap: Map<number, string> = new Map([
[0, "info"],
[1, "success"],
[2, "warning"],
[3, "error"],
]);
interface PrivilegeShape<T extends number | boolean> {
[P: string]: T;
}
// 会员特权
const MemberPrivilege: PrivilegeShape<boolean> = {
// 折扣
discount: true,
// 免运费
freeShipping: false,
};
列表类型
// 列表项1
interface ListItem1 {
id: number;
// 标题
title: string;
// 价格
price: number;
// 促销
promotion: boolean;
// 库存
stock: number;
// 描述
desc: string;
}
// 列表项2
interface ListItem2 {
id: number;
// 标题
title: string;
desc: string;
// 其它属性
others: {
children: number[];
};
}
// 列表
let list: (ListItem1 | ListItem2)[] = [];
// 集合
const productionIds: Set<number> = new Set([1, 2, 3, 4]);
const userNames: Set<string> = new Set(["a", "b", "c"]);
树
interface TreeData {
id: number;
parentId: number | null;
groupId?: number;
name: string;
phone: number;
}
type Tree<T extends TreeData> = {
id: number;
level: number;
data: T;
children?: Tree<T>[];
};
第三方库
声明文件从来源上可以分为2种:
-
一种是自己写的可能放在本地,当然可以以包的形式发布到typescript 声明文件库。
-
还有一种第三方库的声明文件,typescript 声明文件平台,搜索要安装的声明文件,
有的包在你安装时,就附带安装声明文件,相对比较贴心。如:axios, 放在 node_modules/axios/index.d.ts 有的要自己单独安装,如:express。
// 请先用命令 npn i axios 或者 yarn add axios
// 以 axios 为例,直接import 需要的类型
import axios, { AxiosRequestConfig } from "axios";
// 请求拦截器
const reqInterceptor = (config: AxiosRequestConfig): AxiosRequestConfig => {
// 做一些拦截处理
return config;
};
axios.interceptors.request.use(reqInterceptor);
函数类型
// 获取数据列表
function fetchList<T>(params: { id: number; name: string } & Pagination) {
return axios.post<{ total: number; data: T[] }>("/list", params);
}
fetchList<{ id: number; [p: string]: unknown }>({
id: 0,
name: "",
current: 1,
pageSize: 10,
});
type TreeNode = {
id: number;
name: string;
children?: TreeNode[];
};
/**
*
* @param list 数组节点
* @param targetId 查看的id
* @param stack 追逐位置信息
*/
function getArrayIndex(
list: TreeNode[],
targetId: number,
stack: number[] = []
): number[] {
list.some((item, idx) => {
stack.push(idx);
const found = item.id === targetId;
if (!found) {
const { children = [] } = item;
if (children.length > 0) {
const len = stack.length;
getArrayIndex(children, targetId, stack);
return stack.length > len ? true : (stack.pop(), false);
} else {
stack.pop();
}
}
return found;
});
return stack;
}
结语
每一个程序都是对数据加工处理,抽象成数据类型声明,可以举一反三,试着写一写。写声明文件是typescipt,完全聚焦类型的一个方式,没有一点业务在里面。那为什么, 我们不试一试呢?
文章中如有错漏,欢迎指正,谢谢。