规范TS项目Any类型的使用

本文探讨了在React项目中过度使用any带来的问题,并提供了解决方案,包括如何规范地定义复杂类型、利用TypeScript的特性进行类型推断及使用第三方库时的类型定义技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

在使用React的开发项目时,大多数关于ts的类型定义问题,可以在备忘单里面找到;但是当遇到数据类型为数组,对象的时候,为了方便,使用any来进行定义,或者直接用空数据来初始化,当项目变得庞大时,一个组件可能会包括20多个any,使得不容易维护。
由于any会完全失去类型判断,其实是比较危险的,使用any就相当于放弃了类型检测,也就基本上放弃了typescript。
规范化TS的写法,将更有利用项目更好地维护,提高代码的可读性。

使用any较多的场景

定义变量时,变量的数据来源于接口,而接口数量多,定义起来稍显繁杂,所以不进行定义,使用any;
由于变量定义为any,使用该变量进行处理时,也只能使用any;
使用到antd等一些库,遇到函数中的event等参数,不知道如何去定义其类型,直接使用any;
不规范使用Ts举例:

// bad
const [templateTableList,setTemplateTableList] = useState<any>([])

//bad
const [templateTableList,setTemplateTableList] = useState([])

// bad
const temp: any = templateTableList.filter((item:any) => {
   return item.identifier === value;
});

// bad
const onChangeExist = (e: any) => {
  setIsExist(e.target.value);
};

知识补充:TS类型推断

基本类型推断
Ts会进行基本类型的类型的推断,如:

const [val, toggle] = React.useState(false);
等同于:
const [val, toggle] = React.useState<boolean>(false);

复杂类型推断
但是对于数组或者对象,当无法推断一个变量时发出一个错误(或者只能推断为一个隐式的 any 类型)时,我们可以:

  1. 通过显式添加 :any 的类型注解,来让它成为一个 any 类型;
  const onChangeExist = (e: any) => {
    setIsExist(e.target.value);
  };
  1. 通过一些更正确的类型注解来帮助 TypeScript 推断类型。
  import type { RadioChangeEvent } from 'antd/lib/radio';
  
  const onChangeExist = (e: RadioChangeEvent) => {
    setIsExist(e.target.value);
  };

显然,后者更符合我们的开发习惯。

解决any出现次数过次的问题

复杂类型的类型定义

  1. 细拆出重复定义的公共项,使用extents 关键字或者 & 交叉运算符来进行整合,提高利用率;
例1:
// bad
interface Person {
	firstName: string;
  lastName: string;
 }
  
interface PersonWithBirthDate {
	firstName: string;
  lastName: string;
  birth: Date;
 }
// good
interface Person {
	firstName: string;
  lastName: string;
}
interface PersonWithBirthDate extends Person {
	birth: Date;
 }
例2:
export type List = {
  creatTime: number | string;
  creator: string;
  desc: string;
  id: string;
  modifier: string;
  token: string;
  updateTime: number | string;
};

export type ProjectList = {
  id: string;
  projectName: string;
  [key: string]: any;
} & List;

export type TaskList = {
  name: string;
  [key: string]: any;
} & List;

新的问题:如果很多字段要打问号怎么办?下面会讲到

  1. 使用typeof定义一个类型匹配初始值(常见的使用场景之一:固定的Schema配置适用)
const INIT_OPTIONS= {
	width: 640,
  height: 480,
  color: "#00FF00",
  label: "VGA",
};

interface Options {
	width: number;
  height: number;
  color: string;
  label: string;
}

// 快速获取配置对象的形状
type Options = typeof INIT_OPTIONS;
  1. 使用Ts 内置类型来解决?号太多的问题
  • Utility Types
  • 充分利用lib.es5.d.ts中的Partial, Pick , Extract, Omit等方法,扩展第三方、或已存在的类型,不要重复定义完全一样的字段,详细的内容请戳

使用IDEA智能联想推断类型:以antd为例

antd里面事件参数event的定义
例如: 在RadioGroup组件中,绑定一个onChange事件,如下:

<Radio.Group onChange={onChangeExist} value={isExist}>
	<Radio value="Exist">Exist</Radio>
	<Radio value="NotExist">Not Exist</Radio>
</Radio.Group>

这种情况下,需要层层深入去查找RadioGroup的实现才能知道e是如何定义的,比较繁杂

  const onChangeExist = (e: any) => {
    setIsExist(e.target.value);
  };

一个比较简便的方法:
步骤1:将事件的写法修改为:

<Radio.Group onChange={(e)=>{onChangeExist(e)} value={isExist}>
	<Radio value="Exist">Exist</Radio>
	<Radio value="NotExist">Not Exist</Radio>
</Radio.Group>

步骤2:将鼠标放到参数 e 上去,可以显示出参数的类型
在这里插入图片描述
步骤3:引入类开,修改any类型为:RadioChangeEvent ,同时恢复onChange的写法:

<Radio.Group onChange={onChangeExist} value={isExist}>
	<Radio value="Exist">Exist</Radio>
	<Radio value="NotExist">Not Exist</Radio>
</Radio.Group>
  import type { RadioChangeEvent } from 'antd/lib/radio';
  
  const onChangeExist = (e: RadioChangeEvent) => {
    setIsExist(e.target.value);
  };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值