dva + typescript 尝试

typescript很火,虽然我觉得良好注释的javascript就已经可以了,但形势比人强,还是尝试一下typescript吧。

使用的脚手架是公司基于dva-cli修改的,所以可能会和dva-cli生成的有点区别。编辑器是vscode

首先,新建tsconfig.json文件,内容如下:

// tsconfig.js
{
  "compilerOptions": {
      "strictNullChecks": true,
      "moduleResolution": "node",
      "allowSyntheticDefaultImports": true,
      "experimentalDecorators": true,
      "jsx": "preserve",
      "noUnusedParameters": true,
      "noUnusedLocals": true,
      "target": "es6",
      "lib": [
          "dom", 
          "es7"
      ]
  },
  "exclude": [
      "node_modules",
      "lib",
      "es"
  ]
}

再新建一个typings.d.ts文件,解决非代码模块的引入。

// typings.d.ts
// 这里是 less 文件的声明
declare module "*.less" {wuzuixiao
  const content: any
  export default content
}

然后,将routes/IndexPage.js改成routes/IndexPage/index.tsx,启动项目,浏览器正常打开。当然,到目前为止还没有开始typescript的编码,routes/IndexPage/index.tsx里的是anyscript。接下来,简单的写点什么:

// routes/IndexPage/index.tsx
import React from 'react';
import { connect } from 'dva';
import styles from './index.less';
import Link from './components/Link'
import ShowText from './components/ShowText'

interface DocumentItem {
    link: string,
    target: string,
    text: string
}

interface Props {
    example: {
        document: Array<DocumentItem>
    }
}

function IndexPage(props: Props): JSX.Element {
    const { document = [] } = props.example
    return (
        <div className={styles.normal}>
            <h1 className={styles.title}>Hello, Let's start <ShowText text="TypeScript" /> with <ShowText text="dva" /></h1>
            <ul className={styles.list}>
                {
                    document.map((item: DocumentItem, index: number) => {
                        return (
                            <li key={index}>
                                <Link link={item.link} target={item.target} text={item.text} />
                            </li>
                        )
                    })
                }
            </ul>
        </div>
    );
}
// routes/IndexPage/components/Link.tsx
import * as React from 'react'

interface Props {
  link: string,
  target: string,
  text: string
}

function Link(props: Props): JSX.Element {
  return (
    <a target={props.target} href={props.link}>{props.text || props.link}</a>
  )
}

export default Link
// routes/IndexPage/components/ShowText.tsx
import * as React from 'react'

export interface Props {
  text: string
}

class ShowText extends React.Component<Props> {
  render() {
    const { text = '' } = this.props
    return (
      <span>{text}</span>
    )
  }
}

export default ShowText
// model 层数据

import u from 'updeep';

const STATE = {
    document: [
        {
            link: 'https://typescript.bootcss.com/tutorials/react.html',
            target: '_blank',
            text: 'TypeScript'
        },
        {
            link: 'https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md',
            target: '_blank',
            text: 'dva.js'
        }
    ]
};

export default {

    namespace: 'example',

    state: u(STATE,null),

    subscriptions: {
        setup({ dispatch, history }) {
        },
    },

    effects: {
    },

    reducers: {
    },
};

项目可能不全是typescript,所以,需要兼容js文件,此外,还要能使用alias别名。修改后的tsconfig.json如下:

// tsconfig.json
{
    "compilerOptions": {
        "strictNullChecks": true,
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "experimentalDecorators": true,
        "jsx": "preserve",
        "noUnusedParameters": true,
        "noUnusedLocals": true,
        "target": "es6",
        "lib": [
            "dom",
            "es7"
        ],
        "allowJs": true,
        "baseUrl": ".",
        "paths": {
            "@src/*": [
                "src/*"
            ]
        }
    },
    "include": ["src/**/*"],
    "exclude": [
        "node_modules",
        "lib",
        "es",
        "dist"
    ]
}

jsconfig.json的配置如下:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "@src/*": ["src/*"]
        }
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules","dist",".cache"]
}

配置好之后,编辑器会报错无法写入文件“c:/projects/start-typescript/src/components/IndexPage.js”,因为它会覆盖输入文件。出现类似这种错误的原因是在tsconfig.json的配置中出现了allowJs: true,并且项目中有js文件。ts编译的目标文件就是js文件,而现在js文件已经存在,所以报错。这种报错可以不管,不影响项目的开发和打包。