之前用了一段時間的flow,發現配合 Atom + Nuclide 還是不夠智能,于是開始嘗試使用 Vue + Webpack + Vuex + Vue-router + Typescript (夾帶了 pug 和 sass) 的超級全家桶進行開發。剛入門就發現各種小問題,雖然都解決了,但是好像中文資料這方面比較欠缺,做個記錄好了。
#1 Vue type declarations 類型聲明
在這里我使用了 Vue 官方的 vue-class-component
一開始使用的是 vue-property-decorator ,發現相比 vue-class-component 多了一些高階函數的修飾器,并且寫起來更加復雜,根據實際情況最后該回了 vue-class-component
vue-class-component 服用方式
更新:好了,發現要使用 watch 還是要上 vue-property-decorator,于是又改回來了
#2 在項目中使用webpack code splitting
在SPA應用中,當模塊數量特別多,或者單個模塊特別大的時候,打包成一個文件很明顯是個不明智的舉動,這個時候就需要 webpack code splitting 來動態加載模塊代碼了。
很常規的一個做法就是按路由區分,在 Vue 項目中 routes 對象中使用 require.ensure() 的方法加載對應的代碼。但是在 webpack + Typescript 的項目中,因為沒有對應的類型聲明,該方法 ts-loader 會報錯 ts2304,谷歌一搜就有,安裝一個 @types/webpack-env 就好了
npm install --save @types/webpack-env
npm 地址 戳這里
#3 并不屬于Vue,是JSX的,也有一點關系
const renderBoard = props.squares.map((row, rowIndex): JSX.Element => {
return (
<div className="board__row" key={rowIndex}>
{rowIndex}
</div>
)
})
在一個React組件中,我使用了Array.map()的方法返回了一個值為JSX.Element的數組,但是在render方法中不可以用方法的調用方式renderBoard()來進行調用,會出現 Error: Cannot invoke an expression whose type lacks a call signature
的錯誤,正確的寫法是直接把 renderBoard 當成一個變量使用,這個變量返回了一個含有 JSX.Element 的數組
#4 Node 模塊回調中 this 的 type 為 any
Node 中使用 mongoose 操作 MongoDB,在 mongoose.Schema.pre 中的回調中使用 this,tslint 提示
[ts] 'this' implicitly has type 'any' because it does not have a type annotation.
因為自定義的 Schema 實例實際上真實的 Type annotation 沒有一個很好的實現方法,并且由于是回調函數,typescript 沒法很好的推斷 this 指向的對象。暫時還沒找到更好的辦法,只能忽略 this 的類型檢查(建議使用 2 ):
- 不使用嚴格的類型檢查,即在
tsconfig.json
中設置"strict": false
- 在
tsconfig.json
中設置"noImplicitThis": false
related:
- 官方對于
noImplicitUseStrict
這個選項的解釋是Raise error on this expressions with an implied any type.
-
tsconfig.json
的配置選項可查看官方文檔
#5 聲明 mongoose model 類型
由于在注冊/登錄接口中使用了
bcrypt-nodejs
,在userSchema.methods
上掛載了相關的方法需要在
controller 中調用,而 typescript 卻告訴我User
的類型上沒有這些方法。Google了一下解決,源碼如下:
export type UserModel = mongoose.Document & {
name: string,
...
generateHash: (password: string) => string,
validPassword: (password: string) => boolean,
}
export let User = mongoose.model('User', userSchema) as mongoose.Model<UserModel>
PS. as
will calls a type assertion. (不清楚怎么翻譯好,自己意會吧)
#6 PM2 直接運行部署 Typescript 項目
PM2 作為 node.js 生產環境的部署利器,Typescript 的支持自然是少不了。可惜的是,我在執行
pm2 start src/server.ts
的時候 PM2 告訴我 ts-node
看起來是無效的。如下圖:
使用了并不存在的打開會404的搜索引擎找了一下,在 GitHub 上找到了解決辦法,使用 pm2 install typescript
命令安裝一下運行 Typescript 所需的環境(實際上就是拷貝了 typescript
和 ts-node
的內容至 node_modules/pm2
下)即可。
最終執行結果如下 :