文章首发于:github.com/USTB-musion…前端
Typescript是JavaScript的一个超集,主要提供了类型系统和对es6的支持。本人使用ts编写react将近3个月的时间,中间踩了很多坑,从刚开始的以为ts没有必要到如今以为ts真香。在这里对使用ts编写react的心得作一下总结。react
本文将从如下几部分进行总结:git
一个好的代码习惯是经常对本身写的代码进行小的重构,使得代码可维护性更强。可是对于不少线上运行的代码,代码测试覆盖率每每不是很高,有时候哪怕一个变量名的改动,都会牵一发而动全身。而对于使用ts编写的项目就不会有这种担忧。ts的静态检查特性会帮助找出代码中有错误的部分。es6
js是一门动态弱类型解释语言,变量声明后能够改变类型,并且类型须要在运行时才能肯定。而ts的报错提示是在编译时,不是在运行时。因此使用ts带来的静态类型检查等特性将使得IDE的提示更加完善。github
当你接手一个有历史包袱的项目时,确定会头疼于文档和代码注释的缺失,而对于ts来讲,是能够作到代码即文档的,经过声明文件能够知道哪些字段的含义以及哪些字段是必填和选填的。举个简单例子,当封装一个button的组件时:typescript
export interface ButtonProps {
style?: React.CSSProperties
className?: string
label?: React.ReactNode
type?: 'primary' | 'default' | 'search'
size?: 'sm' | 'md' | 'lg' | 'mini'
disabled?: boolean
title?: string
onClick?: ((e: React.MouseEvent<HTMLButtonElement>) => void)
}
复制代码
经过这些声明文件能够知道,当使用这个button文件时,style是一个可选值,表示一个能够自定义样式的style字段。type也是一个可选值,表示按钮的颜色类型,能够选择'primary','default','mini'其中的一种。disabled也是一个可选值,传入的值必须是boolean类型。因此就能够看出类型声明自己就是很是好的文档。bash
如下是官网的一个例子,建立Props和State接口,Props接口接受name和enthusiasmLevel参数,State接口接受currentEnthusiasm参数。less
import * as React from "react";
export interface Props {
name: string;
enthusiasmLevel?: number;
}
interface State {
currentEnthusiasm: number;
}
class Hello extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { currentEnthusiasm: props.enthusiasmLevel || 1 };
}
onIncrement = () => this.updateEnthusiasm(this.state.currentEnthusiasm + 1);
onDecrement = () => this.updateEnthusiasm(this.state.currentEnthusiasm - 1);
render() {
const { name } = this.props;
if (this.state.currentEnthusiasm <= 0) {
throw new Error('You could be a little more enthusiastic. :D');
}
return (
<div className="hello">
<div className="greeting">
Hello {name + getExclamationMarks(this.state.currentEnthusiasm)}
</div>
<button onClick={this.onDecrement}>-</button>
<button onClick={this.onIncrement}>+</button>
</div>
);
}
updateEnthusiasm(currentEnthusiasm: number) {
this.setState({ currentEnthusiasm });
}
}
export default Hello;
function getExclamationMarks(numChars: number) {
return Array(numChars + 1).join('!');
}
复制代码
无状态组件也称为傻瓜组件,若是一个组件内部没有自身的state,那么组件就能够称为无状态组件。在@types/react已经定义了一个类型type SFC<P = {}> = StatelessComponentpost
。咱们写无状态组件的时候,能指定咱们的组件为SFC或StatelessComponent。它已经预约义了children,displayName等。 以button为例:学习
import React from 'react'
const Button = ({ onClick: handleClick, children }) => (
<button onClick={handleClick}>{children}</button>
)
复制代码
若是采用ts来编写出来的无状态组件是这样的:
import React, { MouseEvent, SFC } from 'react';
type Props = { onClick(e: MouseEvent<HTMLElement>): void };
const Button: SFC<Props> = ({ onClick: handleClick, children }) => (
<button onClick={handleClick}>{children}</button>
);
复制代码
react规定不能经过this.props.xxx和this.state.xxx直接进行修改,因此能够将State和Props标记为不可变数据:
interface Props {
readonly number: number;
}
interface State {
readonly color: string;
}
export class Hello extends React.Component<Props, State> {
someMethod() {
this.props.number = 123; // Error: props 是不可变的
this.state.color = 'red'; // Error: 你应该使用 this.setState()
}
}
复制代码
在工做中,可能常常会使用Event对象,change事件可使用React.ChangeEvent, click事件可使用React.ChangeEvent。
onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
// do something
}
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// do something
}
复制代码
React 能够渲染一些像 JSX 或者是 string 的内容,这些被合并到类型 React.ReactNode 中,所以,当你接收可渲染的内容时,你可使用它:
type Props = {
header: React.ReactNode;
body: React.ReactNode;
};
class MyComonent extends React.Component<Props, {}> {
render() {
return (
<div>
{this.props.header}
{this.props.body}
</div>
);
}
}
<MyComponent header={<h1>Header</h1>} body={<i>body</i>} />
复制代码
在大中型前端项目中,因为js的动态弱类型特性,致使不少错误在运行时才发现。ts做为js的超集,为前端开发带来了编译时的检查,将不少的错误避免在了编译阶段。也为IDE带来了更强的智能提示。虽然学习ts会花一些时间,但这些时间是值得的。使用ts开发项目以后,明显发现项目的可维护性变强了,bug率下降了,查文档也更加方便,一看类型声明文件就明白了各个字段的含义。