使用 TypeScript

什么是 TypeScript

TypeScript 简称 TS,是微软开发的 javascript 加强版,顾名思义就是带了 type 的 javascript。它的很多特性可以帮助我们写出更加健壮的代码,弥补 javascript 在开发大型项目时的先天不足。

TypeScript 允许你以 接口 的形式定义复杂的类型。当你要在应用程序中使用复杂的 对象或数组(例如包含其他属性的对象)时,会进行严格的静态类型审查,增加健壮性。

开始一个 demo

接下来让我们来使用 antd 开发一个功能完备的 crud 应用程序来带我们认识一下 TypeScript 的优越之处。在 umi 中内置了 TypeScript 的 Loader,你可以直接新建 .tsx 或者 .ts 文件来写 TypeScript 代码。demo 地址

首先我们安装依赖包

cnpm install tslint tslint-config-prettier tslint-react @types/react @types/react-dom --save

然后我们需要新建 tsconfig.jsontslint.json文件,tsconfig.json 来声明这是一个 TypeScript 项目,并且进行配置。详细配置可以参考官网,我们可以直接直接输入如下内容:

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es2016",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "jsx": "react",
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "experimentalDecorators": true
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
    "tslint:latest",
    "tslint-config-prettier"
  ]
}

tslint 类似 eslint 是一个代码风格检查器。tslint.json我们可以直接使用如下配置:

{
  "extends": ["tslint:latest", "tslint-react", "tslint-config-prettier"],
  "rules": {
    "no-var-requires": false,
    "no-submodule-imports": false,
    "object-literal-sort-keys": false,
    "jsx-no-lambda": false,
    "no-implicit-dependencies": false
  }
}

为了增加使用体验,建议一并安装 vscode tslint 插件。

我们可以先做一个简单的 demo 来感受一下 TypeScript 的魅力。首先在 src/page 新建一个 Demo.tsx. 在其中定义一个无状态组件 Hello。

import React from 'react';

const Hello = ({ name }) => <div>Hello,{name}</div>;

接下来我们使用它,

const App = () => <Hello />;

export default App;

我们发现他抛出了如下错误 :

不能将类型“{}”分配给类型“{ name: any; }”。类型“{}”中缺少属性“name”。

因为我们使用了 name,Typescript 认为他是必填参数。如果不存在便认为程序错误,并造成编译失败。这可以帮助我们避免很多低级错误。

我们还可已将 name 使用 SFC 进一步约束,规定 name 为 string 类型,来增加健壮性。

const Hello: React.SFC<{ name: string }> = ({ name }) => (
  <div>Hello,{name}</div>
);

我们也可以使用 Class 语法来声明组件,代码如下:

class Message extends React.Component<{
  message: string;
}> {
  public render() {
    return <div>{this.props.message}</div>;
  }
}

我们可以通过 <> 的第一个参数来指定 props 的类型。通过第二个参数来指定 state 的类型,代码如下:

class Message extends React.Component<
  {
    message: string;
  },
  {
    count: number;
  }
> {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  public render() {
    return (
      <div>
        {this.props.message}
        {this.state.count}
      </div>
    );
  }
}

在这里,我们定义了一个 包含 count 的 state ,count 的类型为 number。然后在类 constructor 内部初始化 state。其余使用方式与 javascript 中相同。

我们可以自行修改 count,

public increment = () => {
  const { count } = this.state;
  this.setState({
    count: count + 1
  });
};

并且将其绑定到 dom 上,

public render() {
  return (
    <div onClick = {this.increment}>
      {this.props.message}
      {this.state.count}
    </div>
  );
}

使用 Message 组件:

const App = () => <Message message="点击"/>;

export default App;