TypeScriptで Vueを書いてみよう!

06a095e125c2016e983e183e10209b9a?s=47 jiko21
June 22, 2019

TypeScriptで Vueを書いてみよう!

v-kansai Vue.js/Nuxt.js meetup #7の登壇資料です

06a095e125c2016e983e183e10209b9a?s=128

jiko21

June 22, 2019
Tweet

Transcript

  1. TypeScriptで Vueを書いてみよう! Vue/Nuxt meetup #7 Daiki Kojima (@Daikids2)

  2. https://speakerdeck.com/daikids2/typescriptde-vuewoshu-itemiyou

  3. ⼩島⼤基 (Daiki Kojima) • Student@京⼤院(情報学) • Twitter: @Daikids2 • GitHub:

    daikikojima
  4. Index • What is TypeScript • TSでコンポーネントを書いてみる • VuexでもTSを書いてみる •

    まとめ
  5. What is TypeScript

  6. About TypeScript • Microsoftが開発したAltJSの⼀種 • ES5のスーパーセット • 型とか、ClassとかInterfaceが使える

  7. 型が使えてうれしいこと… • JSだとこのまま実⾏されてしまう。 • 予期せぬバグの原因に • ちなみに… • add(a,b) ->

    11 (string型) • mul(a,b) -> 1 (number型) function add (a, b) { return a + b; } function mul (a, b) { return a * b; } const a = 1; const b = “1"; add(a, b); mul(a, b);
  8. TSだとこう書ける! • トランスパイルの段階で はじかれるし、 VS Codeとかだと、書くだけで 怒られる function add(a: number,

    b: number): number { return a + b; } function mul(a: number, b: number): number { return a * b; } const a = 1; const b = "1"; console.log(add(a, b)); console.log(mul(a, b));
  9. Interfaceが使えるぞ!! • (僕的には)TS使う⼀番の理由だったりする… • Object内のプロパティとその型を記述したもの • こんなやつです↓ export default interface

    Todo { content: string; status: number; key: string; }
  10. JSDocとの違い • JSDocは何回も書く必要あり? • TSなら⼀度どっかに書いとけばそれをimportするだけでいい • entities/*.tsとか、models/*.tsとか /** * @param

    todo TODO Entity Object * @param {string} todo.content actual task * @param {number} todo.status status: {todo->0, doing->1, done->2} * @param {string} todo.key firebase key */ export default interface Todo { content: string; status: number; key: string; }
  11. TSでComponentを書いてみる

  12. 気になったら… • https://github.com/daikikojima/Open-CharTo に実際に動かしているコードがあります。

  13. その前に… • Vue cliのバージョンは3以上 • @vue/cliを使う • vue-cliはもうdeprecated • Nuxtの場合はまだ知らないです…

  14. Creating project • 思考停⽌してもできます!

  15. Class Style Componentって? import Vue from 'vue'; import {mapGetters, mapActions,

    mapState} from 'vuex'; export default Vue.extend({ name: 'Header’, props: { isToggled: { type: Boolean, required: true, }, doLogout: { type: Function, required: true, }, toggleBurger: { type: Function, required: true, }, }, computed: { ...mapGetters( ['isLoggedIn’], ), }, }); 普通に書いた場合 (Object Style)
  16. Class Style Componentって? import {Component, Prop, Vue} from "vue-property-decorator"; import

    {mapGetters, mapActions, mapState} from 'vuex'; @Component({ computed: { ...mapGetters( ['isLoggedIn’], ), }, }) export default class Header extends Vue { @Prop() private isToggled!:boolean; @Prop() private doLogout!:() => {}; @Prop() private toggleBurger!:() => {}; } 型周りはきれい
  17. 実は… https://github.com/vuejs/rfcs/pull/17#issuecomment-494242121

  18. RFCでは採⽤されないことに… • Rfc上でdropされました… • エッジケース・仕様依存・未解決の問題があるため • composition functionsのほうがいい ってEvan Youが⾔ってました…

    • 未だに@vue/cliでは使うに決まってるよね、 と聞かれます
  19. VuexもTSで書いてみる

  20. Vuexってなんだっけ… • FluxをVueで簡単にやろうぜ! っていうやつ • Vuejsが管理しているように、 Vueで簡単に扱えるように作られている。

  21. 公式の画像やけど… https://vuex.vuejs.org/ja/

  22. そのまえに… Page固有の Store Root Store • 基本的にこんな感じで ディレクトリ構成を考える

  23. Actions • VueからActionを受け取る部分 • この中にどんどんactionを定義していく const actions: ActionTree<TopState, RootState> =

    {... initialize({ commit }) { const user = this.state.user; if (user !== null) { firebaseRdbService.getTodos(user, (todos: TodoResponse|null) => { if (todos !== null) { commit('setTodos', objModule.objectToArrayWithKey(todos!)); } }); } },
  24. もし、RootStateを定義しない場合… • Anyで逃げてください • 特に、Reducksパターンとか、ページごとにStateが独⽴なら こうなることがあるかも! const actions: ActionTree<TopState, any>

  25. Mutations • めっちゃかんたん • ここでも引数に型、つけられます! const mutations: MutationTree<TopState> = {...

    const mutations: MutationTree<TopState> = { setTodos(state: TopState, todos: Todo[]): void { state.todos = todos; }, };
  26. Getters • これもかんたん! • 普通のTypeScriptですよね… const getters: GetterTree<TopState, RootState> =

    {... const getters: GetterTree<TopState, RootState> = { getAllTodos(state: TopState): TodoPacks|null { return { todo: filterTodos(state.todos, 0), doing: filterTodos(state.todos, 1), done: filterTodos(state.todos, 2), }; }, ...
  27. こうすると嬉しかったこと… • どこからどんなobjectが来るかが明⽰的にわかる! • いったんtypesとか、modelsみたいなとこに書いとけば それを参照するだけでいい! • 実際にはentitiesディレクトリを作ってそこにinterfaceは書いてます

  28. ただし…

  29. 当然⾟い部分も出てくる…

  30. (個⼈的に)⾟かった部分 • Router部分のGuardの引数とか… • 参考してたサイトに従って型定義したけどダメ • (いま書いたりしてるけど)テストとか… • wrapper.vmにpropとかdataがないと⾔いやがる注意してくれる…

  31. 解決策

  32. Anyを使おう!! • そもそもここら辺ってあんま厳密な型はいらなそう • テストなんて動いてくれればいいでしょ (正論)

  33. Anyが恥ずかしいと思う⽅へ… https://twitter.com/__gfx__/status/1127816243040227330

  34. Anyは恥ずかしいくない!! • 確かに、Vue + TSは厳密にやろうとすると⾟い… •でも、使えるとこだけうまいことつかおうや?

  35. まとめ • VueもTSで書く時代です。 • Componentを書くのはつらいかもしれない • Vuexはわりかし書きやすい •Anyは恥じゃない!!