larrykkk/notes

Vue 2 + TypeScript 筆記

Opened this issue · 12 comments

求大大(TypeScript)手下留情

Vue cli 開新專案的時候就會問 要不要安裝 Typescript 了

但如果你是現有的專案要加 Typescript 怎辦?

$ vue add typescript

reference: https://medium.com/@ngubanethabo.ambrose/adding-typescript-to-an-existing-vue-cli-project-499e5125d04a

其他優質整合文章:
How to Integrate Typescript with Vue.Js

接下來就是一連串的問題問你要不要裝某某套件

  • Use class-style component syntax? Yes
    (Q: 阿如果選 No 怎辦? Ans: 用 Basic Usage,語法有差以外,似乎 type interface 功能也有影響,端看個人決定)
  • Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
  • Convert all .js files to .ts? Yes
  • Allow .js files to be compiled? Yes

基本上我都選 Yes,因為還不知道幹嘛用的,都先試試看

本來以為寫完 $ vue add typescript 以後就好辦了,沒想到才是開始

嗯 噴了幾個紅紅的 error

ERROR in E:/bpgcms/source/frondend/src/apis/index.ts(4,15):
4:15 Parameter 'email' implicitly has an 'any' type.       
    2 | export default {
    3 |   apiUrl: process.env.VUE_APP_API_URL,
  > 4 |   async login(email, password) {
      |               ^
    5 |     let result = await axios
    6 |       .post(`${this.apiUrl}/api/v1/login`, {       
    7 |         email: email,
ERROR in E:/bpgcms/source/frondend/src/apis/index.ts(4,22):
4:22 Parameter 'password' implicitly has an 'any' type.    
    2 | export default {
    3 |   apiUrl: process.env.VUE_APP_API_URL,
  > 4 |   async login(email, password) {
      |                      ^
    5 |     let result = await axios
    6 |       .post(`${this.apiUrl}/api/v1/login`, {
    7 |         email: email,

這邊是在跟你說 function 參數後面必須定義型別,於是我們給他加上該有的型別。

來到 apis/index.ts line 4 做修改

async login(email: string, password: string) {

解決~

接下來是這個

ERROR in E:/bpgcms/source/frondend/src/plugins/element.ts(4,20):
4:20 Could not find a declaration file for module 'element-ui/lib/locale/lang/zh-TW'. 'E:/bpgcms/source/frondend/node_modules/element-ui/lib/locale/lang/zh-TW.js' implicitly has an 'any' type.
  Try `npm install @types/element-ui` if it exists or add a new declaration (.d.ts) file containing `declare module 'element-ui/lib/locale/lang/zh-TW';`        
    2 | import Vue from 'vue'
    3 | import Element from 'element-ui'
  > 4 | import locale from 'element-ui/lib/locale/lang/zh-TW'
      |                    ^
    5 | 
    6 | Vue.use(Element, { locale })
    7 | 

解決辦法: ElemeFE/element#9084 (comment)

然後一切都沒問題之後,打開首頁?靠怎麼是預設的畫面

原來 $ vue add typescript 完以後大部分檔案都被改掉改成初始狀態了...

App.vue

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';

@Component({
  components: {
    HelloWorld,
  },
})
export default class App extends Vue {}
</script>

<style lang="scss">
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

改回來

<template>
  <div class="wrapper">
    <router-view></router-view>
  </div>
</template>

<script lang="ts">
import { Vue } from 'vue-property-decorator';
export default class App extends Vue {
  name!: string;
}
</script>

這中間有遇到的問題: microsoft/TypeScript-Vue-Starter#36
以及 vue-property-decorator

錯誤解決方式

因為某種需要使用了 event bus,但在 console 裡面會一直跳上面這個錯誤,搜尋了一下之後發現原來官網文件裡面就有講到,不過看得不是很懂。

後來在 CSDN 找到一篇文章有提供詳細的範例
可以直接翻 types/index.d.ts & types/vue.d.ts 這兩隻檔案看作法

  • “Property ‘resetFields’ does not exist on type ‘Vue | Element | Vue[] | Element[]’. Property ‘resetFields’ does not exist on type ‘Vue’.

在 node_modules/element-ui/src/types/form.d.ts 裡面可以找到已經定義好的 types,所以就直接拿來用吧

import { Form } from 'element-ui';
...
(this.$refs[formName] as Form).resetFields();

同場加映 resetFields() 解法

import { Form } from 'element-ui';
...
(this.$refs[formName] as Form).validate(async (valid) => {
  if (valid) {
    alert('submit!');
  } else {
    return false;
  }
});

也可以參考這裡 & 這裡

不要在 src/views 裡面的 .vue 檔用 vue-class-component 的寫法,不然錯到連你媽媽都認不得你是誰

vue 2.x Typescript 的整合很差,官網文件幾乎沒有

Vue + Typescript

目前為止最熱門(完整?)的套件是
vue-class-component (官方)
vue-property-decorator (擴充官方上面的)(使用中)

Vuex 也是,詳情請見討論串

Write Stores in Typescript

目前為止最熱門(完整?)的套件是 vuex-module-decorators
https://github.com/ktsn/vuex-class

其他

vuex-persist - 將 vuex store 儲存 Localstorage (預設,可變更),使資料不會因為重新整理而消失
vue-typescript-admin-template - use element-ui

viT-1 commented

Vue 2 typescript examples with vuex & without webpack/rollup (tsc transpiling & bundling):

  • simple with SystemJs module resolving only
  • tough with esm & SystemJs support, eslint & jest (gulp-replace for esm modules resolving)