使用 TypeScript

TypeScript is a superset of javascript that adds a lot of useful features compared to javascript:

  • 类型批注和编译时类型检查
  • 类型推断
  • 类型擦除
  • 接口
  • 枚举
  • Mixin
  • 泛型编程
  • 名字空间
  • 元组
  • Await
    使用 TypeScript 对 IDE 会更加友好,如果你是用 vscode 开发的,那么你的开发体验将会显著提升。基于 umi 的特性,我们可以很容易的在 Pro 中使用。 Pro 中自带了 TypeScript 所需的配置文件.

  • tsconfig.js

  • tslint.json
    tsconfig 会声明这是一个 TypeScript 的项目,其中会进行一些配置,详细内容可以看这里。 tslint 类似 eslint 将会检查你的代码,为了提升体验,可以一并安装 vscode 的 tslint 插件。接下来我们只要直接新建 tsx 文件,就可以开始 TypeScript 开发了。

常见问题

在 css-module 中使用

由于 Pro 使用了 css-module,你可能需要

  1. import style from './index.style.less';

这时候 typescript 会报错,你可以 使用

  1. const style = require('./index.less');

避开这个问题。社区有很多相关讨论,暂时没有最好的办法,只有相对完美的 typings-for-css-modules-loader,同理导入图片,css,svg 也可以通过这种方式避开类型检查。

Form.create()

在 TypeScript 中使用 Form.create() 可能会抛出类似下面的错误:

  1. error TS2339: Property 'loading' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Compone
  2. nt<{}, ComponentState>> & Readonly<{ childr...'.

这是因为 props 的类型没有通过检查,以下是正确的方式

  1. import { FormComponentProps } from "antd/lib/form/Form";
  2. interface IFormComponentProps extends FormComponentProps {
  3. test: string;
  4. }
  5. class FormComponent extends React.Component<IFormComponentProps> {
  6. constructor(props: IFormComponentProps) {
  7. super(props);
  8. ....
  9. }
  10. render() {
  11. const { getFieldDecorator } = this.props.form;
  12. return ....;
  13. }
  14. }

没有描述文件的仓库

在实际使用有些库并没有相关的 d.ts,这个时候我们可以直接在使用的文件中定义,以高德地图为例。

  1. import React from 'react';
  2. // 定义 Map 的 类型
  3. declare class GaoDeAMap {
  4. constructor(container: HTMLElement, option: { center: [number, number]; zoom: number });
  5. public destroy(): void;
  6. }
  7. // 定义全局的 AMap
  8. declare const AMap: {
  9. Map: typeof GaoDeAMap;
  10. };
  11. // tslint:disable-next-line:max-classes-per-file
  12. class MapComponent extends React.Component {
  13. public mapDom: HTMLDivElement;
  14. public map: GaoDeAMap;
  15. public componentDidMount() {
  16. const map = new AMap.Map(this.mapDom, {
  17. center: [117.000923, 36.675807],
  18. zoom: 11,
  19. });
  20. this.map = map;
  21. }
  22. public componentWillUnmount() {
  23. this.map.destroy();
  24. }
  25. public render() {
  26. return <div ref={ref => (this.mapDom = ref)} />;
  27. }
  28. }
  29. export default MapComponent;

如果要多次使用,可以建立一个 namespace,

  1. declare namespace AMap {
  2. class Map {
  3. constructor(
  4. container: HTMLElement,
  5. option: { center: [number, number]; zoom: number }
  6. )
  7. public destroy(): void
  8. }
  9. }
  10. export = AMap
  11. export as namespace

然后在项目中直接引入就可以了。

  1. import AMapInterface from './AMap';
  2. `
  3. declare const AMap: typeof AMapInterface;