やりたいこと
- Vue3のコンポーネントで
props
の型を定義したい- Enumで作った自作型を指定したい
- コンポーネントはVue3のComposition APIで定義するものとする
-
<script setup>
内のdefineProps
でprops
を定義する
-
※<script setup>
についてはコチラから↓
ダメーな例: ts2769が出ちゃうやつ
筆者が当初、TypeScriptランタイムからトムブラウン風に「ダメー」と言われちゃったコードがこちらです。
<!-- とあるコンポーネント -->
<script setup lang="ts">
import { defineProps } from 'vue';
import { Page } from '@/enums';
const props = defineProps({
currentPage: {
required: true,
type: Page, // No overload matches this call...(ts2769)
}
});
</script>
このコードでは、別ファイルで定義されたEnum型のPageをprops
のtype
に指定しようとしていますが、TypeScriptエラーが発生します。
defineProps
で定義する際は、type
に指定する型をVueが提供している組み込みの型で定義してあげる必要があるのですが、どうやらTypeScript特有のEnum型は組み込みに含まれていないようです。それが原因で「ダメー」が起きています。
※多分同じことで困っている型々方々↓
解決法
方法1. アロー式を使う
Enumで定義した自作型をtype
に指定する方法の一つとして、アロー式を使用する方法があります。
<script setup lang="ts">
import { defineProps } from 'vue';
import { Page } from '@/enums';
const props = defineProps({
currentPage: {
required: true,
type: String as () => Page,
}
});
</script>
String as () => Page
が肝です。as
演算子の後ろでPage
型(Enum)へ変換するための関数型を記述することで型アサーションを実現しています。
要はTypeScriptの機能を用いて解決しているのが、この解決方法と言えます。
方法2. PropTypeを使う
もう一つの方法として、Vue3のPropType
を使用する方法があります。これは、Vue3の組み込みの型指定機能を利用する方法です。
<script setup lang="ts">
import { defineProps, PropType } from 'vue';
import { Page } from '@/enums';
const props = defineProps({
currentPage: {
required: true,
type: String as PropType<Page>,
}
});
</script>
今度はString as PropType<Page>
が肝です。当然、PropTypeはVueの組み込みの型なので、当初出ていたエラーは消えます。おめでとうございます。
Vue.jsの機能を用いて解決しているのが、この解決方法と言えます。
どちらを選ぶべきか
Vue.jsのプロジェクトである以上、props
の定義に際しては「方法2. PropTypeを使う」の方が一般的な解決方法なのかと考えています。
公式ドキュメントでもPropType
の利用を推奨している雰囲気があります。
とはいえ、props
に関わらない場面で普通に型アサーションを使う機会は多くあるので、その際にはアロー式を使うこともあるはずです。場面に応じて使い分けましょう、と思いました。
まとめ
TypeScriptたのしいね!!!