实际开发中TypeScript 使用记录

React 组件中根据一个props类型去推断另一个props类型

业务场景

在实际开发中我遇到这样一个场景,有一个表单组件既可以填写国家代码,也可以填写国家区号和手机号;

  • 国家代码时, 表单接收string 类型;
  • 国家区号和手机号时,表单接收 string[ ]数组分别对应区号,手机号;
  • fieldType 定义为一个联合类型 'telCode' | 'countryCode' 分别表示手机区号和国家区号表单项。
CountryCode TelCodePhone

功能清楚了,就可以写props了,最开始可能写成这个样子

typescript 复制代码
  interface  MyCountryFieldProps {
      value: string | string[]
      fieldType: 'telCode' | 'countryCode'
      ....
  }

问题

这样写会埋一个坑:

  • 期望: value类型其实是根据fieldType 判断的,为countryCode它应该是string类型,telCode才是string[]
  • 实际: 你的类型定义告诉别人,传valuestring 或者 string[]都可以,但很明显传错了,组件很出问题了。

解决办法

解决思想其实很简单就行告诉ts,ts帮我判断一下 countryCode它应该是string类型,telCode才是string[]

这里我们用了对象的联合类型知识点:

typescript 复制代码
type MyCountryFieldProps = {
    fieldType: 'telCode'
    value: string[]
    ...
} | {
    fieldType:  'countryCode',
    value: string
    ...
}

如图,ts很清晰的告诉我们传错了值的类型,并且告诉该怎么改,这就是TS代码即注释魅力。后面再也不用担心别人用错了。

当然,组件会有其他很多prop,写两份似乎有些笨重,那我们改一下,我们可以使用交叉类型 变化和不变的分组在用&拼接。

typescript 复制代码
type MyCountryFieldProps = {
      fieldType: 'telCode'
      value: string[]
     } | {
     fieldType:  'countryCode'
     value: string
   }&{
     otherProps1?:string
     otherProps2?:string
     otherPropsFun3?:()=>void
     ...
   }

是否可以使用泛型解决呢?

泛型:是可以理解对应为js里的函数,需要传入"类型参数",并在泛型调用时才确定具体类型,把上面联合类型改成泛型就如下。

typescript 复制代码
type MyCountryFieldProps<T extends 'telCode' | 'countryCode'>={
   fieldType:T,
   value: T extends 'telCode' ? string[] : string; 
  }
tsx 复制代码
    type MyCountryFieldProps<T extends 'telCode' | 'countryCode'>={
      fieldType:T,
      value: T extends 'telCode' ? string[] : string; 
    }

    const MyCountryField:FC<MyCountryFieldProps<typeof props.fieldType>> = ({fieldType,value}) => {
      console.log(fieldType);
      console.log(typeof value);
      return (
        <>
          MyCountryField
        </>
      )
    }

这里typeof props.fieldType 是伪代码,假设获取props.fieldType类型值,如果可以取到确实是可以使用泛型定义的,但是笔者查了一下:

复制代码
React 组件的 props 是在组件实例化之前静态确定的,而不是在运行时动态确定的。

似乎是获取不到,所以也就不能使用泛型了,但我们使用联合类型,也完全满足我们的业务场景,还是挺不错的。

总结

通过上面一个真实的业务需求,我们切实感受到ts代码即注释的魅力 。如果延伸一下的话,通过联合类型定义,我们就可以根据一个或多个props类型,去推断其他props类型定义。

相关推荐
yinuo9 分钟前
前端跨页面通讯终极指南⑥:SharedWorker 用法全解析
前端
PineappleCoder5 小时前
还在重复下载资源?HTTP 缓存让二次访问 “零请求”,用户体验翻倍
前端·性能优化
拉不动的猪5 小时前
webpack编译中为什么不建议load替换ast中节点删除consolg.log
前端·javascript·webpack
李姆斯5 小时前
Agent时代下,ToB前端的UI和交互会往哪走?
前端·agent·交互设计
源码获取_wx:Fegn08955 小时前
基于springboot + vue健身房管理系统
java·开发语言·前端·vue.js·spring boot·后端·spring
闲谈共视5 小时前
基于去中心化社交与AI智能服务的Web钱包商业开发的可行性
前端·人工智能·去中心化·区块链
CreasyChan6 小时前
C# 反射详解
开发语言·前端·windows·unity·c#·游戏开发
JIngJaneIL6 小时前
基于Java+ vue智慧医药系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
hashiqimiya7 小时前
两个步骤,打包war,tomcat使用war包
java·服务器·前端
零度@8 小时前
Java中Map的多种用法
java·前端·python