TypeScript在实际场景中的应用技巧
创作时间:
作者:
@小白创作中心
TypeScript在实际场景中的应用技巧
引用
CSDN
1.
https://blog.csdn.net/2402_85402030/article/details/139591795
TypeScript在实际开发中的应用远不止基础类型的学习。本文通过多个实际项目案例,展示了如何利用TypeScript的高级类型功能来优化代码结构,提高开发效率。无论是避免类型重复定义,还是组件封装,亦或是自定义类型检查,这些技巧都能帮助开发者更好地驾驭TypeScript。
避免类型的重复定义
在实际项目中,我们经常会遇到需要对同一数据结构在不同场景下定义不同类型的情况。TypeScript提供了一些内置类型工具,可以帮助我们更优雅地处理这类问题。
/** 定义基本的数据项 */
type Item = {
id: number;
name: string;
age: string;
address?: string;
};
/** 列表数据,泛型的基本用法,也可以Item[] */
type List = Array<Item>;
/** 新增时表单数据,无id,使用Omit移除属性 */
type FormDataAdd = Omit<Item, 'id'>;
/** 修改时表单数据,只可修改address,使用Pick挑选属性 */
type FormDataModify = Pick<Item, 'id' | 'address'>;
const data: Item = {
id: 1,
name: 'xx',
age: 18,
address: 'xxx',
};
/** 当确定address必有值,使用NonNullable转换一下 */
const addressMustExist = data.address as NonNullable<Item['address']>;
/** 或者使用非空断言 */
const addressMustExist1 = data.address!;
/** 查询参数,使用Partial将属性转为可选,使用&扩展属性 */
type Query = Partial<List> & {
current: number;
pageSize: number;
};
/** 定义一个通用的service,泛型T 表示数据项,U 表示查询参数 */
type Service<T, U> = (params: U) => Promise<{ data: T[]; totalItem: number; }>;
/** 运用 */
type PageService = Service<Item, Query>;
组件的二次封装
在React项目中,我们经常需要对第三方组件库(如Ant Design)进行二次封装,以满足特定业务需求。TypeScript的类型系统可以帮助我们更安全地进行这类封装。
import { Input, InputProps } from 'antd';
import { useMemo } from 'react';
interface IProps extends Omit<InputProps, 'disabled'> {
myCustomProps?: string;
}
export default function MyInput(props: IProps) {
const { myCustomProps, ...restInputProps } = props;
const computedDisabled = useMemo(() => {
if (myCustomProps === 'xxx') {
return true;
}
return false;
}, [myCustomProps]);
return <Input {...restInputProps} disabled={computedDisabled} />;
}
字符串格式限制
有时候我们需要对字符串的格式进行限制,比如表示一个数值范围的字符串。TypeScript的模板字面量类型可以帮助我们实现这一点。
function range(num: number, interval: `${'[' | '('}${string}${')' | ']'}`) {
// 实现省略...
}
ahooks的useAntdTable二次封装
ahooks的useAntdTable
是一个非常实用的hook,但有时我们需要对service的返回格式进行适配。通过TypeScript的泛型和条件类型,我们可以优雅地处理这类问题。
import { useAntdTable } from 'ahooks';
import { AntdTableOptions, Data, Params } from 'ahooks/lib/useAntdTable/types';
/** 我们的返回数据类型 */
export type MyData = {
success: boolean;
data: {
list: any[];
totalItem: number;
};
};
/** 我们的service入参 */
export type MyParams = {
currentPage: number;
pageSize: number;
[key: string]: any;
};
/** 定义接受的service类型,extends关键词保证了service符合我们的定义约束 */
type MyService<TData extends MyData, TParams extends MyParams> = (args: TParams) => Promise<TData>;
/** 获取Promise的返回值类型,这里用到了infer,通常用来搭配泛型来获取某个具体的类型 */
type PromiseType<T> = T extends Promise<infer U> ? U : never;
/** 结合useAntdTable的类型定义,来修改我们要的类型 */
function useDrsAntdTable<TData extends MyData, TParams extends MyParams>(
service: MyService<TData, TParams>,
options: AntdTableOptions<Data, Params> = {},
) {
type returnType = PromiseType<ReturnType<typeof service>>;
/**
* 我们需要把对应类型也做转换,手动赋给useAntdTable的泛型参数,让TS识别到
* 通常使用useAntdTable时并不需要指定这个泛型,是因为TS可以从service中推断出来
*/
type TransformData = {
list: returnType['data']['list'];
total: number;
};
const hooks = useAntdTable<TransformData, Params>(async ({ current, pageSize }, params) => {
const { data } = await service({
currentPage: current,
pageSize,
...params,
});
return {
total: data.totalItem,
list: data.list,
};
}, options);
return hooks;
}
export default useDrsAntdTable;
使用封装后的hook,代码会简洁很多,同时dataSource的类型也能得到正确的提示:
热门推荐
“医保取现”透支未来“救命钱” 多部门联合严查违规行为
雨水节气养生指南:中医专家推荐5个秘诀和2道食疗方
如何带领团队精进工作
2分钟看懂音箱的RMS功率是什么?对声音有什么影响?怎么选?
期价创近一年半来新低!苯乙烯持续走弱的原因是……
益生菌懒人包:益生菌何时食用?可以长期服用吗?附益生菌食物
如何提高目标任务完成率?五个关键策略让你事半功倍
生物素:维生素B7的全面解析
芝麻粉、芝麻醬、芝麻油該如何保存?原來它不需要放冰箱!
实用!坐火车不小心上错了该咋办?这份出行攻略快收好
7岁男孩专属阅读指南:六大领域精选书籍推荐
装修攻略:有限预算下的高性价比材料选购指南
核电钢结构科研创新与精益建造前后台多项目管理实践
青岛探索骑手友好社区:让“配送之路”更舒心更顺畅
4级甲状腺结节就是癌?消融术比传统手术更好?如何保护“脆皮”甲状腺?
咳嗽完全攻略:咳嗽不止常见原因跟止咳方法,看这一篇就够了!
出现心绞痛别不当回事,心脏正在发出紧急求助信号,远离5个诱因
Adobe Photoshop中添加签名或水印的两种方法
湘财股份与大智慧计划跨界融合 两家“联姻”可追溯至10年前
外出关掉这几个设置 手机续航提升20%
科学护肤:先认识这些护肤成分
如何有效清洗发动机积碳?这种清洁方法对发动机性能有何影响?
光伏设计需要考虑哪些关键方面?
德甲情报:药厂头牌因伤缺阵,波鸿化身巨人杀手
糖尿病医保报销比例及额度详解:职工医保与城乡居民医保有何不同?
蓄电池容量及内阻测试方法详解
手机储存照片清晰度指南:从拍摄到存储的全方位优化
关于提高儿童免疫力的方法解读
春秋五霸的雄风:齐桓公率先称霸
春秋霸业的奠基者:齐桓公