本文共 4033 字,大约阅读时间需要 13 分钟。
「优雅」的含义:
import * as React from 'react';// 如果在tsconfig中设置了"allowSyntheticDefaultImports": true// 你还可以更精练地import react:// import React from "react";interface IProps { // CSSProperties提供样式声明的类型信息 // 用户传入style的时候就能够获得类型检查和代码补全 style?: React.CSSProperties; // 使用@types/react提供的事件类型定义,这里指定event.target的类型是HTMLButtonElement onClick(event: React.MouseEvent): void; // ...}const MyComponent: React.FC = (props) => { const { children, ...restProps } = props; return {children};}
IProps
无需声明children
属性的类型。React.FC
会自动为props添加这个属性类型。
当然,如果children期望一个render prop,或者期望其他特殊的值,那么你还是要自己给children
声明类型,而不是使用默认的React.ReactNode
。
props
无需做类型标注。函数组件defaultProps(Deprecate)
如果你需要定义defaultProps,那么不要使用React.FC,因为:
const defaultProps = { who: "Johny Five"};type IProps = { age: number } & typeof defaultProps;export const Greet = (props: IProps) => { return123};Greet.defaultProps = defaultProps;
事实上,,所以以后还是尽量减少在函数组件上使用defaultProps,使用ES6原生的参数解构+默认参数特性就已经能够满足需要:
const TestFunction: FunctionComponent= ({ foo = "bar" }) => {foo}
interface IProps { message: string;}interface IState { count: number;}export class MyComponent extends React.Component{ state: IState = { // duplicate IState annotation for better type inference count: 0 }; render() { return ( {this.props.message} {this.state.count}); }}
如果你通过声明state属性来初始化state,那么你需要为这个属性增加IState类型标注。虽然这与前面的React.Component<IProps, IState>
有重复的嫌疑,但是这两者实际上是不同的:
React.Component<IProps, IState>
只是标注了基类的state属性类型。this.state
会以子类中的state属性声明作为类型信息的来源。可渲染节点就是:可以直接被组件渲染函数返回的值。
与可渲染节点有关的类型定义如下(摘录自):
type ReactText = string | number;type ReactChild = ReactElement | ReactText;interface ReactNodeArray extends Array{}type ReactFragment = {} | ReactNodeArray;type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
React.FC<Props>
(即 React.FunctionComponent<Props>
)React.Component<Props, State>
React.ComponentType<Props>
(即ComponentClass<P> | FunctionComponent<P>
)
const withState =( WrappedComponent: React.ComponentType
,) => { ...
比如,以下例子获取并扩展了<button>
的props类型:
export const PrimaryButton = ( props: Props & React.HTMLProps) => ;
PrimaryButton能够接受所有原生<button>
所接受的props。关键在于React.HTMLProps
。
import { Button } from "library"; // but doesn't export ButtonProps! oh no!type ButtonProps = React.ComponentProps; // no problem! grab your own!type AlertButtonProps = Omit ; // modifyconst AlertButton: React.FC = props => (
@types/react提供了各种事件的类型,比如以下是使用React.FormEvent
的例子:
class App extends React.Component< {}, { text: string }> { state = { text: '', } onChange = (e: React.FormEvent): void => { this.setState({ text: e.currentTarget.value }) } render() { return ( ) }}
在React中,所有事件(包括、、等)都是的子类型。他们在@types/react中定义如下:
// DOM事件的基本属性都定义在这里interface BaseSyntheticEvent{ nativeEvent: E; currentTarget: C; target: T; bubbles: boolean; cancelable: boolean; defaultPrevented: boolean; eventPhase: number; isTrusted: boolean; preventDefault(): void; isDefaultPrevented(): boolean; stopPropagation(): void; isPropagationStopped(): boolean; persist(): void; timeStamp: number; type: string;}interface SyntheticEvent extends BaseSyntheticEvent {}// 具体的事件类型:interface FormEvent extends SyntheticEvent {}interface KeyboardEvent extends SyntheticEvent { altKey: boolean; // ...}interface MouseEvent extends SyntheticEvent { altKey: boolean; // ...}// ...
转载地址:http://hiqni.baihongyu.com/