简介
声明文件语法
- 示例 ^2
1 | // 全局变量 |
tsconfig.json
- 常用配置(基于vue项目)
1 | { |
Vue结合Typescript
Vue项目改造成支持TS ^3
安装依赖(项目基于vue-cli@3.X创建)
1
2
3
4# @vue/cli-plugin-typescript 为解析ts语法插件,基于 ts-loader
npm install typescript @vue/cli-plugin-typescript -D
# Vue 相关特性的装饰(注解)
npm install vue-class-component vue-property-decorator -S加入
tsconfig.json
文件,参考上文加入
src/shims-vue.d.ts
垫片(shims-vue文件名可随便取)1
2
3
4
5
6
7
8/**
* 告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理
* 而在代码中导入 *.vue 文件的时候,需要写上 .vue 后缀。原因还是因为 TypeScript 默认只识别 *.ts 文件,不识别 *.vue 文件
*/
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}(可选)加入
shims-tsx.d.ts
让vue来处理jsx语法1
2
3
4
5
6
7
8
9
10
11
12
13import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any
}
}
}修改
main.js
为main.ts
- 代码中导入
*.vue
文件的时候,需要写上.vue
后缀 (可选)部分场景可能需要在
vue.config.js
或webpack增加相关配置(以vue-cli为例)1
2
3
4
5
6
7
8module.exports = {
configureWebpack: {
// 入口文件
entry: {
main: ['src/main.ts']
}
}
}
- 代码中导入
(可选)对于额外挂载在vue原型上的变量,可使用类型增强进行声明。如在src任意目录创建
service.d.ts
(或者添加在 shims-vue.d.ts 中)1
2
3
4
5
6
7
8import Vue from 'vue';
declare module 'vue/types/vue' {
interface Vue {
$ajax: any;
$apiUrl: string;
}
}vue的javascript语法转typescript语法异同:https://www.cnblogs.com/wenxinsj/p/13297155.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44import { Component, Prop, Watch, Mixins, Vue } from "vue-property-decorator";
import CommonFunc from './CommonFunc'
// 不加 @Component 注解,会报一些奇奇怪怪的错:(1)is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property(说子组件的DOM中不能直接使用prop,需要data接收。实际是子组件中可直接使用prop)(2)Error in render: "TypeError: vnode.children.slice is not a function"
// @Component // 此缩写也行
({
components: { XXXComp }
})
export default class Order extends Mixins(CommonFunc) {
type: String, default: "" }) init!: string; ({
// data
value: string = ''
"tokenExpire", { immediate: true, deep: true }) (
changeToken(val: "tokenExpire") {
}
// computed
get loginUrl() {
let { loginUrl } = this.commonHosts;
return loginUrl;
}
created() {
this.hello()
}
}
// CommonFunc.ts 文件名建议大写
import { Vue, Component, Prop, Watch, Mixins } from "vue-property-decorator";
export default class CommonFunc extends Vue {
hello: any = null;
get helloName() {
return this['value'] + this.hello + 'Name'
}
hello () : void {
console.log('hello...')
}
}
Vue组件script标签引入模块
1 | <!-- js方式 --> |
Webpack转译Typescript现有方案
- 方式一:
ts-loader + babel-loader
^1- 当 webpack 编译的时候,ts-loader 会调用 typescript(所以本地项目需要安装 typescript),然后 typescript 运行的时候会去读取本地的 tsconfig.json 文件
- vue-cli内置
ts-loader
- 默认情况下,ts-loader 会进行转译和类型检查,每当文件改动时,都会重新去转译和类型检查,当文件很多的时候,就会特别慢,影响开发速度。所以可以搭配
fork-ts-checker-webpack-plugin
,开辟一个单独的线程去执行类型检查的任务,这样就不会影响 webpack 重新编译的速度。并行构建不再适合新版本的 webpack 了- 并行化构建有两种方式: happypack 和 thread-loader
- 并行化构建对于 webpack 2/3 的性能有明显的提升,使用 webpack 4+时,速度提升的收益似乎要少得多
- 方式二:
babel-loader + @babel/preset-typescript
- 当 webpack 编译的时候,babel-loader 会读取 .babelrc 里的配置,不会调用 typescript(所以本地项目无需安装 typescript),不会去检查类型。但是 tsconfig.json 是需要配置的,因为需要在开发代码时,让 IDE 提示错误信息
- 方式三:
awesome-typescript-loader
(停止更新) - 问题说明
- 使用了 TypeScript,为什么还需要 Babel
- 大部分已存项目依赖了 babel,有些需求/功能需要 babel 的插件去实现(如:按需加载)
- babel 有非常丰富的插件,它的生态发展得很好;babel7 之前,只能用上述1/3两种方案来转译 TS;babel7 之后,babel 直接移除 TS,转为 JS,这使得它的编译速度飞快
- 为什么用了 ts-loader 后,还要使用 babel-loader
- ts-loader 是不会读取 .babelrc 里的配置,即无法使用 babel 系列的插件,所以直接使用 ts-loader 将 ts/tsx 转成 js ,就会出现垫片无法按需加载、antd 无法按需引入的问题。所以需要用 ts-loader 把 ts/tsx 转成 js/jsx,然后再用 babel-loader 去调用 babel 系列插件,编译成最终的 js
- Typescript 官方转向 ESLint 的原因
- TSLint 执行规则的方式存在一些架构问题,从而影响了性能,而修复这些问题会破坏现有规则;
- ESLint 的性能更好并且使用者较多
- 使用了 TypeScript,为什么还需要 ESLint
- TS 主要是用来做类型检查和语言转换的,顺带一小部分的语法检查
- ESLint 主要是用来检查代码风格和语法错误的
- 如果在使用 babel-loader + @babel/preset-typescript 这种方案时,也想要类型检查
- 再开一个 npm 脚本自动检查类型:
"type-check": "tsc --watch"
,tsconfig.json中配置compilerOptions.noEmit=true
- 再开一个 npm 脚本自动检查类型:
- 使用 @babel/preset-typescript 需要注意有四种语法在 babel 中是无法编译的
- namespace(已过时)
- 类型断言:
let p1 = {age: 18} as Person;
- 常量枚举:
const enum Sex {man, woman}
- 历史遗留风格的 import/export 语法:
import xxx= require(…) 和 export = xxx
- 使用了 TypeScript,为什么还需要 Babel
临时
- 忽略TS报错
1 | # 单行忽略(包含//) |
参考文章