Typescript 開發過程記錄(Vue.js/Node.js/React.js)

之前用了一段時間的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 服用方式

vue-class-component in typescript

更新:好了,發現要使用 watch 還是要上 vue-property-decorator,于是又改回來了

#2 在項目中使用webpack code splitting

在SPA應用中,當模塊數量特別多,或者單個模塊特別大的時候,打包成一個文件很明顯是個不明智的舉動,這個時候就需要 webpack code splitting 來動態加載模塊代碼了。

webpack code spliting

很常規的一個做法就是按路由區分,在 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 ):

  1. 不使用嚴格的類型檢查,即在 tsconfig.json 中設置 "strict": false
  2. 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 看起來是無效的。如下圖:

Screen Shot 2017-09-25 at 1.37.43 PM.png

使用了并不存在的打開會404的搜索引擎找了一下,在 GitHub 上找到了解決辦法,使用 pm2 install typescript 命令安裝一下運行 Typescript 所需的環境(實際上就是拷貝了 typescriptts-node 的內容至 node_modules/pm2 下)即可。

Screen Shot 2017-09-25 at 1.39.45 PM.png

最終執行結果如下 :

Screen Shot 2017-09-25 at 1.59.02 PM.png
Screen Shot 2017-09-25 at 1.39.52 PM.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容