📖

Vue 2 × TSX で完璧な型サポートを手に入れる

2021/07/02に公開

この記事は、昨日会社のテックブログに寄稿した記事

https://tech.andpad.co.jp/entry/2021/07/01/170000

に入りきらなかった情報の補足です。

元の記事では、Vue + JSX + Nuxt Composition APIという組み合わせで開発を行う際の、環境設定・導入方法、メリットとデメリット、そしてJSXに限らないComposition APIのTipsまでいろいろ書いていますので、興味のある方は先にそちらの記事をご覧ください【PR】!


さて、冒頭の記事ではVue + JSX(TSX)の組み合わせでの開発のメリデメを挙げる中で、

現状のVue + JSXの弱点として「ReactほどHTMLの型定義が厳密ではない」ということを書きました。

冒頭に掲載した shims-tsx.d.ts をよく見るとわかりますが、属性はstring、中身はanyになっており、例えば <div href={3}> のような定義を行ってもエラーにはなりません。
(中略)
なお、Vue 3では型定義ファイルを内包するため、上記のライブラリは不要となっています。
まだ実際には試せていませんが、vue-nextのjsx.d.tsを見るとかなり詳細な定義がされており、Reactと同様の強力な型チェックサポートが期待できます。

ここで触れている shims-tsx.d.ts は以下のような定義です。

import { VNode } from 'vue';
import { ComponentRenderProxy } from '@vue/composition-api';

declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends ComponentRenderProxy {}
    interface ElementAttributesProperty {
      $props: any; // specify the property name to use
    }
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

で、確かにVue Composition APIの公式ページにも、この型定義ファイルを使え、と書いてあるので、公式資料に従うと、型サポートをほとんど受けられないということになります。

ところが、この記事を書いて提出した後にいろいろ調べたところ、実はVue 2でもVue 3やReactと同等の厳密な型サポートを手に入れる方法がありました。

それは、shims-tsx.d.tsの中身を丸ごとVue 3のjsx.d.tsに置き換えるやり方です。

https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/types/jsx.d.ts

このファイルの中身をそのままコピーして、プロジェクト内のshims-tsx.d.tsを丸ごと上書きする形で貼り付けます。

そして、コメントを除いた1行目である

import { VNode } from '@vue/runtime-core'

import { VNode } from 'vue'

に書き換えます。

そして改めてTSXで記述されたVueファイルを編集してみると…

この通り、特定のタグにしかない属性も含めて完璧に型サポートを受けられました!

vue-tsx-support のようなプラグインを別途導入する必要もなく、記事で触れたコンポーネントライブラリとの相性問題などもなく。とても手軽です。

最初はVue 2 と Vue 3 の差分でうまくいかないのではと思いましたが、VNodeのimport元が異なり、それ以外は基本的にHTML Tagの属性を定義しているだけなので、おそらく問題なさそうです。

少なくとも自分は今のところ使っている限りではよくわからないエラーが出たりはしていません。

とはいえ公式に推奨されている方法ではないので、自己責任でお願いします。(この確証がなかったので元記事には書きませんでした)

良いVue + TSXライフを!

Discussion