没有特殊原因建议还是不要过快往vue中加入typescript,typescript和vue是比较成熟,但vue刚添加支持,契合度以及资料等都比较少,所以容易踩到坑,写起来并不顺手。
记得之前 Evan 也说过要支持typescript的事情,不过因为 vue 的一些特性与 typescript 比较难以兼容,所以放弃了,本来以为不会太快官方支持 ts ,没想到2.5就接受了来自 ts 官方团队的PR。
下面介绍一下,最近学习 ts 的一些教训和心得。
typescript简称ts,是 javascript 的一个超集,也就是在 javascript 上设置一层封装,加入了 ts 的功能特性,最终检查编译为js。
function hello(msg: string): void {
console.log(`hello, ${msg}`);
}
hello('laolei'); // true
hello(12); // Argument of type '12' is not assignable to parameter of type 'string'
ts加入的根本目的还是添加可选的静态类型编程方式,相对于 flow 这种类型检查器语言侵入性比较小,API 相对灵活易用,在上面代码中进行函数声明时只需定义传入参数类型以及函数返回值类型即可,如果调用或者编写函数时与静态类型产生冲突,那么在 ts 进行编译检查时即会报错。
function hello(msg) {
console.log("hello, " + msg);
}
hello('laolei');
编译后的结果还是我们想要的
大概原理主要是编译+执行,主要分为三步:
上图就是基本流程了
Scanner
ts的编译机制会根据当前 ts 依赖、配置等情况进行源码扫描,生成相应 Token
Parse
Token会被解析成 AST(abstract syntax tree,抽象语法树)
Checker
根据前面生成的 symbol 进行最重要的检查部分
Emmiter
生成最终JS
包括是 JS 中基本类型和引用类型,以及自己比较强的扩展类型
Boolean,布尔值类型检查:const light : boolean = true
String,字符串类型检查:const name : string = 'allen'
Number,数字类型检查:const count : number = 5
Null和Undefined,null和undefined类型检查
const u : undefined = undefined
const n : null = null
数组类型检查:const list : number[] = [1, 2, 3]
空值 void 表示没有值,多用于表示函数没有返回值:
function say() : void {
console.log('hello')
}
Any 金手指,建议尽可能少使用,相当于禁掉类型检查let notSure: any = 4; notSure = "maybe a string instead
另外还有never(没有值的类型)元组 枚举等
常用的还有 interface、class等特性,总体来说在v2版本中,TS 已经是比较全面的了
// 对对象属性进行检查的利器
interface name {
firstName: string
lastName: string
}
const myName = {
firstName: liu
lastName: allen
}
// TS 的新特性支持度非常高,许多尚在stage中的特性都有所实现(当然有些也是实验性特性),在class中,我们可以使用 public、private、protected等关键字
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name); this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
vue2.5刚发布没多久,vue-cli正在支持 vue + TS 开箱即用,不过在那之前,还是要进行一系列麻烦的配置,如果习惯用 vue-class-component 的可能还要配置 vue-decorator-property 依赖。
VUE的官方 TS 类型声明文件也是早已发布,TS 即从这里面早已定义好的类型声明进行检查,同时核心插件vuex和vue-router也有声明文件
配置主要需要进行以下几项修改
typescript
ts-loader
vue-class-component
vue-decorator-property
@types 文件依赖(依赖库的类型声明文件,包括.d.ts文件)
要修改一些webpack的一些写死的开发生产环境公用代码
在 build/webpack.base.conf.js 中
// 入口函数后缀
entry: {
app: './src/main.ts'
}
// 在extensions中加入.ts选项,可以默认引入文件不加.ts后缀
resolve: {
extensions: ['.js', '.ts', '.vue', '.json']
}
// 加入ts-loader的处理规则
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/]
}
}
]
}
所有要类型检查的JS文件后缀改为 .ts,vue单文件中改为
所有import引入的文件必须指明后缀名,否则会被默认当做.ts文件处理
在所有class前加上 @component,最终会写成
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class Publish extends Vue{
// 组件选项
}
在 src 目录添加vue-shim.d.ts文件,
declare module "*.vue" {
import Vue from "vue";
export default Vue;
}
对TS的声明文件,因为 TS 默认并不处理 .vue 文件,所以要告诉TS .vue 文件可以交给 vue 模块进行处理
在根路径下创建tsconfig.json文件
{
"compilerOptions": {
// 与 Vue 的浏览器支持保持一致
"target": "es5",
// 这可以对 `this` 上的数据属性进行更严格的推断
"strict": true,
// 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake:
"module": "es2015",
"moduleResolution": "node"
// 使用实验性的decorators特性
"experimentalDecorators": true,
"strictFunctionTypes": false,
// 允许使用非ts文件
"allowJs": true
}
}
大概就这几项需要修改的地方,可以参考我的项目
TS 无疑给 JS 带来了很多的改善,它以其低侵入性,在运行之前的编译过程中对类型进行检查后再输出运行源码,而我们只需要使用其强大的静态类型检查系统就可以避免在开发过程中的很大一部分程度的错误,我认为其有如下优势
提供了一种良好的协作方式,利用其接口类型的显示化降低团队协作成本,使团队水平参差不齐带来的影响降低
拥有良好的语言及周边设计,微软的丰富语言设计经验,vs code等 IDE 的配合,良好的lint系统,精准的代码提示,及时的代码检错提示,JS语言的最新特性支持
项目可维护性、可读性大大提高,极大降低 bug 出现几率
期望未来 TS 会越来越好,JS生态越来越强