仕事で本格的にTypeScriptを使うことになりそうなので色々調査したりしているが、調べている過程でうまくいかないところがいくつかあったので簡単にまとめておく。
Nuxt.js+TypeScript+Jestでのエラー
以下のVueファイルと、TypeScriptで書かれたテストコードがある。
page1.vue
<script lang="ts"> import Vue from 'vue' export default Vue.extend({ data() { return { test: '', } }, }) </script>
page1.spec.ts
import { mount } from '@vue/test-utils' import Page1 from '@/pages/page1.vue' describe('Page1', () => { test('is a Vue instance', () => { const wrapper = mount(Page1) expect(wrapper.vm).toBeTruthy() expect(wrapper.vm.test).toEqual('') }) })
Vueファイルのインポート部分でエラーが出るが、これは型宣言の追加で解決できる(以下の型宣言追加箇所を参照)。
また、describe等のエラーは@types/jest
を追加してtsconfig.jsonのtypes
にjest
を追加することで解決できる。
ただ、wrapper.vm.test
のエラーだけが解決できない(test
というプロパティが存在しないと言われる)。調べた限りではこれの解決方法は2つあった。
1. any型として扱う
以下のように記述することで、少なくとも実行は出来るようになった。
expect((wrapper.vm as any).test).toEqual('')
ただしこれをやると型補完が利かなくなる(wrapper.vm.
まで打ち込んでもtest
が候補に出てこない)。
2. interface等を使う
interface等を使ってtest
というプロパティが存在することを明示的に宣言してやる(出典がどこかは忘れた)。ただVueファイルを作成する度にこれらを宣言するのは心が折れるため、結局試すこと自体しなかった。そもそも出典がどこかも忘れたため、本当にそう書けるかどうかも分からない。
結論
JavaScriptだと普通に動くのでテストコードはJavaScriptで書くことを提案した。そもそもよく考えたら注目すべきは画面側の振る舞いであって内部パラメータにアクセスすること自体不要な気がしてきた。フロントエンドのテストコードをよく分かっていないので何とも言えないが。
型の指定方法
以下のようなファイルがある。
<script lang="ts"> import Vue from 'vue' export interface Interface1 { a: string } export interface Interface2 { a: string } export default Vue.extend({ data(): { test: Interface2 } { return { test: { a: 'a' }, } }, mounted() { this.method1(this.test) }, methods: { method1(arg1: Interface1) { return arg1.a }, }, }) </script>
method1
はInterface1
を引数としているがmounted
で実行される際の引数test
はInterface2
のため、コンパイルエラーが発生するものだと思っていた。ただ、これは問題なく実行できる。
Javaだとインターフェース名が異なれば別のもの扱いだがTypeScriptだと中のプロパティを確認するようなので、同一プロパティを持っていれば問題なく実行できるらしい。そういうように解釈した。
他にもいくつかあったがエディタを変えたら再現しなくなったものとかもありうまくまとめられなかった。また何か見つけたらまとめるかもしれない。