背景:公司项目使用的组件库是ant-design,代码要求用typescript,刚开始写代码,老是红色波浪线😭, 后面索性用any代替一切类型,在使用过程当中编辑器仍是提示一些错误😭,好比使用ant-design的Form组件要使用props.form时必须这样写
Form.create<AddProps>()(Add)
,看到<>
这是啥???好像大学时学c++时见过(只是见过),后面看了几遍文档终于弄明白了,当本身开始真正实操写代码时,又熟悉的红色波浪线😭又出现了,决定写一篇文章结合实际项目的运用,让本身入个门...javascript
A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is generics, that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types. 传送门 (翻译: 为了偷懒及编辑器友好的代码提示)html
为了学习(不报错)泛型,我准备了一个例子,便于快速入门, 个人解说所有放代码注释了,直接看代码。java
// 学习部分
/***************************** * 泛型: (通用的类型) * 泛:(普遍:不少,广泛) * 型: (类型: 好比number, string, object, array) * 下面的T便是泛型(通用类型), T能够随便命名的, 我当初看的时候,觉得只能<T>, <V>这样写。 ***************************/
function identity<T>(arg: T): T {
return arg;
}
// 调用时把T换成真正的类型
identity<string>("myString")
复制代码
代码我简化过哦react
举的栗子是父组件调子组件内部方法c++
/***************************************
* 场景:React在父组件里面,
* 想调用子组件里面的helloWorld函数
*****************************************/
import React from 'react'
import Child from './child'
function Parent(){
// 不使用泛型这样写
const childRef = React.createRef();
// 使用泛型这样写
const childRef = React.createRef<Child>();
return (
<div>
<button onClick={() => {
/*****************************
*使用泛型的好处体现下面这一行代码, 当你敲 childRef!.current!.
* 编辑器会提示组件Child里面的方法, 好比helloWord这个方法。
********************************/
childRef!.current!.helloWorld()
}>调用子组件</button>
<Child ref={childRef}/>
</div>
)
}
复制代码
示例一个泛型组件,并如何在tsx里面使用web
// child.tsx 文件
import React, { Component } from 'react';
/**********************************************
* interface是一个接口, PropsType接受泛型T
*******************************************/
interface PropsType<T>{
sayWhat?: string,
input: T, // input的类型是泛型T
// callback是一个函数,接受2个参数,
callback(input: T, e: React.MouseEvent<HTMLElement>): void
}
/**************************************************************
* childTemplate为泛型,
* PropsType<childTemplate>, 接口PropsType的泛型T被赋值为childTemplate泛型
************************************************/
class Child<childTemplate> extends Component<PropsType<childTemplate>>{
render() {
const { props } = this;
return (<button onClick={(e) => {
console.log(props.sayWhat || '没传sayWhat')
// props.input的类型为childTemplate
props.callback(props.input, e)
}}>子组件</button>)
}
}
// parent.tsx 文件
import React, { Component } from 'react';
import Child from './child'
// 定义接口CTemplate
interface CTemplate{
a: string,
b: number
}
class Parent extends Component{
render() {
// 定义inputChild
const inputChild: CTemplate = {
a: 'hello world',
b: 77
}
return (
// 划重点,在tsx里面的使用,把泛型实例化,这样写<Child<CTemplate> />
<Child<CTemplate> input={inputChild} callback={
(input: CTemplate, e: React.MouseEvent<HTMLElement>) => {
console.log('----------in parent component-------------')
// input里面定义了a和b, 这个时候能够享受编辑器的自动提示了
console.log(input.a + input.b)
console.log(e)
}
}/>
)
}
}
复制代码
准备咱们常常用的From表单讲解一下泛型,加深自个人理解。typescript
在使用ant-design的组件库里咱们常常会用到Form.create这个函数,咱们经过查阅文档来了解它的使用,其实咱们也能够经过它的定义文件来了解它的使用, 光标定位到From.create, 按快捷键(vscode和webstorm快捷键 ctr+B
)进入定义文件bash
// antd/lib/form/Form.d.ts
static create: <TOwnProps extends FormComponentProps<any>>(options?:
FormCreateOption<TOwnProps>) => FormWrappedProps<TOwnProps>;
复制代码
经过上面一行代码,咱们能够获取的信息有:antd
ctr+B
进入定义的地方从上图能够知道,在props里面会有form这个对象。app
ctr+B
定位到定义的地方,ctr+B
定位到定义的地方,咱们能够知道FormWrappedProps是一个函数,(component:C) => ConnectedComponentClass, 参数接受组件,返回组件。export declare type FormWrappedProps<TOwnProps extends WrappedFormInternalProps> =
<C extends React.ComponentType<Matching<TOwnProps, GetProps<C>>>>(component: C) =>
ConnectedComponentClass<C, Omit<TOwnProps, keyof WrappedFormInternalProps>>;
复制代码
看的我头痛....经过上面的一系列ctrl+b
,咱们知道了Form.create的调用方式了,
// YourPropsInterface, FormOption, YourComponent
import React, { useState, Fragment } from 'react';
import { FormComponentProps } from 'antd/es/form';
interface AddProps extends FormComponentProps {
}
function Add(props: AddProps) {
return <div></div>
}
Form.create<AddProps>({name: 'add-component'})(Add)
复制代码
缺点:typescript的泛型(Generics)写起来麻烦,看起来难看
优势:编辑器代码提示,代码更规范,其余小伙伴更容易维护你的代码😰😰😰