vue2.5 與 typescript 不知不說的那些事
前言
沒有特殊原因建議還是不要過快往vue中加入typescript,typescript和vue是比較成熟,但vue剛新增支援,契合度以及資料等都比較少,所以容易踩到坑,寫起來並不順手。
記得之前 Evan 也說過要支援typescript的事情,不過因為 vue 的一些特性與 typescript 比較難以相容,所以放棄了,本來以為不會太快官方支援 ts ,沒想到2.5就接受了來自 ts 官方團隊的PR。
下面介紹一下,最近學習 ts 的一些教訓和心得。
什麼是 typescript
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');
編譯後的結果還是我們想要的
ts編譯過程
大概原理主要是編譯+執行,主要分為三步:
- 解析
- 轉換
- 生成
上圖就是基本流程了
Scanner
ts的編譯機制會根據當前 ts 依賴、配置等情況進行原始碼掃描,生成相應 TokenParse
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}.`;
}
}
vue cli配置 TS
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配置修改
要修改一些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單檔案中<script>
改為<script lang="ts">
所有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生態越來越強