ReactReact.FCimportReact,{HTMLAttributes,PropsWithChildren}from"react";interfaceIHelloPropsextendsHTMLAttributes{name:string;}constHello:React.FC>=({name,children,...rest})=>{return({`你好,${name}!`}
{children}分区>);};使用PropsWithChildren将子类型注入IHelloProps使用React.FC声明组件,通过泛型参数传入组件Props类型注意:React.FC在react@16类型定义中有自己的子类型,不需要额外处理(步骤1可以省略)如果组件需要接受html属性,比如className、style等,可以直接扩展HTMLAttributes
,其中HTMLDivElement可以替换成需要的类型,比如HTMLInputElement。React.FC不推荐?RemoveReact.FCfromTypescripttemplate#8177在本次PR中移除了CRA默认模板的React.FC,主要有以下原因:隐式定义的children不能支持泛型组件挂载静态属性,比较复杂,比如<还有是Select.Option>defaultProps的问题。只有一个好处:提供了返回值约束,所以你可以选择是否使用React.FC。通用组件和安装静态属性属于低频场景。如果你满足他们,你就不需要React.FC。至于德法ultProps在业务代码中基本没有使用(取而代之的是默认值),最新的React.FC已经去掉了内置的children。如果对返回值有明确的类型要求,配置了typescript规则,可以使用React.FC,其他时候可以直接定义Props接口,如下:importReact,{HTMLAttributes,PropsWithChildren}from"react";interfaceIHelloPropsextendsHTMLAttributes{name:string;}constHello=({name,children,...rest}:PropsWithChildren)=>{return(}{`你好,${name}!`}
{children}
);};React.forwardRefReact提供forwardRef函数用于转发Ref。这个函数也可以传入泛型参数,如下:“按钮”;}exportconstFancyButton=forwardRef>((props,ref)=>({props.children}按钮n>));React.ComponentProps用于获取组件props的工具泛型,类似:React.ComponentPropsWithRefReact.ComponentPropsWithoutRefimport{DatePicker}from"@douyinfe/semi-ui";typeSemiDatePikerProps=React.ComponentProps;exportconstDisabledDatePicker:React.FC=()=>{constdisabledDate:SemiDatePikerProps["disabledDate"]=(date)=>{//...};返回;};使用第三方库组件时,不要使用特定路径引用类型(如果第三方组件后续升级修改内部文件引用路径会报错)import{InputProps}from"@douyinfe/半用户界面/输入”;//×import{InputProps}from"@douyinfe/semi-ui";//√如果入口文件没有暴露对应组件的相关类型声明,使用React.ComponentPropsimport{Input}from"@douyinfe/semi-ui";typeInputProps=React.ComponentProps;又如:typenarrowing在一些场景中传入的参数是联合类型,需要通过某种手段来缩小(narrowing)。functionprintAll(strs:string|string[]|null){if(strs&&typeofstrs==="object"){//strs是string[]for(constsofstrs){console.log(s);}}elseif(typeofstrs==="string"){//strs是字符串console.log(strs);}}使用类型谓词:isfunctionisFish(pet:Fish|Bird):petisFish{return(petasFish).swim!==undefined;}if(isFish(pet)){pet.swim();}else{pet.fly();}想想Lodash的isBoolean/isString/isArray...函数,再想想用isEmpty有什么问题。interfaceLoDashStatic{isBoolean(value?:any):值为布尔值;isString(value?:any):值为字符串;isArray(value?:any):valueisany[];isEmpty(value?:any):布尔值;//这里的定义在业务中使用会造成什么问题?}Type-safereduxaction作者没有使用redux,这里只是演示TSPlayground-探索TypeScript和JavaScriptinterface的在线编辑器ActionA{type:"a";a:string;}interfaceActionB{type:"b";b:字符串;}类型Action=ActionA|ActionB;functionreducer(action:Action){switch(action.type){case"a":returnconsole.info("actiona:",action.a);case"b":returnconsole.info("actionb:",action.b);}}reducer({type:"a",a:"1"});//√reducer({类型:"b",b:"1"});//√reducer({类型:"a",b:"1"});//×reducer({type:"b",a:"1"});//×如何在TypeScript中输入Reduxactions和Reduxreducers点?更多收窄方法请参考官方文档-TypeScript文档-收窄多参数类型约束以非常熟悉的window.addEventListener为例://e是MouseEventwindow.addEventListener("click",(e)=>{//...});//e是DragEventwindow.addEventListener("drag",(e)=>{//...});可以发现addEventListener的回调函数的入参类型(事件)会跟在监听的事件后面addEventListener的函数签名如下:addEventListener(type:K,listener:(this:Window,ev:WindowEventMap[K])=>any,options?:boolean|AddEventListenerOptions):void;类型为泛型K,约束在WindowEventMap的key范围内,然后可以根据K从WindowEventMap推导出ev事件类型。当然你也可以选择使用联合类型,就像reduxaction一样。TypeScript类型技巧-多参数类型约束常用工具泛型了解TypeScript基本内容(keyof/in/extends/infer)后,可以尝试自己实现内置工具泛型,以达到更深入的理解。接口人{名称:字符串;年龄:数字;地址?:字符串;}部分。将所有字段更改为可选类型PartialPerson=Partial;//↓typePartialPerson={name?:string|不明确的;年龄?:数字|不明确的;地址?:字符串|未定义;};必需。将所有字段更改为requiredtypeRequiredPerson=Required;//↓typeRequiredPerson={name:string;年龄:数字;address:string;};Pick。从T中获取一些属性KtypePersonWithoutAddress=Pick;//↓typePersonWithoutAddress={name:string;age:number;};省略。从T中删除一些属性KtypePersonWithOnlyAddress=Omit;//↓typePersonWithOnlyAddress={地址?:字符串|未定义;};排除。从T中排除那些可分配给U的类型。泛型实现需要掌握DistributiveConditionalTypestypeT=Exclude<1|2,1|3>;//->2Extract。从T中提取那些可以分配给U的类型。泛型实现需要掌握DistributiveConditionalTypestypeT=Extract<1|2,1|3>;//->1参数。获取函数入参类型declarefunctionf1(arg:{a:number;b:string}):void;typeT=Parameters;//↓typeT=[arg:{a:number;b:字符串;}];返回类型。获取函数返回值类型declarefunctionf1():{a:number;b:string};typeT=ReturnType;//↓typeT={a:number;b:字符串;};记录。将K中所有属性的值转换成T类型。将每个工具泛型理解为一个函数,类型可以作为输入参数和返回值。也可以通过cmd+左键单击特定工具通用来阅读具体实现。工具泛型的具体实现请阅读:TS一些工具泛型的使用及其实现更多内置工具泛型请参考:TypeScriptDocumentation-UtilityTypes推荐阅读TS一些工具泛型的使用及其实现22个例子深入讲解Ts最晦涩的进阶类型工具Reacttsconfig你需要的最少TypeScript常用配置分析TypeScript类型技巧——多参数类型约束TypescriptTips:动态重载实现廉价版依赖类型