IkumaTadokoro / diary

MIT License
0 stars 0 forks source link

2022-06-26 #43

Open IkumaTadokoro opened 2 years ago

IkumaTadokoro commented 2 years ago

VueにおけるTypeScriptの定義

いまいち適当にやっている部分があるんで、ドキュメントに載っている部分から中心に学習する。

環境は前回の反省を踏まえてStackBlitzでやる

https://stackblitz.com/edit/vitejs-vite-kzftqc?file=index.html&terminal=dev

ドキュメントはまずはここかな?

https://vuejs.org/guide/typescript/overview.html

概要

With a Vite-based setup, the dev server and the bundler are transpilation-only and do not perform any type-checking. This ensures the Vite dev server stays blazing fast even when using TypeScript.

今Viteで環境作っているけど、Viteの場合はトランスパイルしかしないから速いって。だからその分、型エラーはIDEでやってくれってさ。 VSCodeでやってもInteliJ系でやってもサポートは受けられるみたい。

If using SFCs, use the vue-tsc utility for command line type checking and type declaration generation. vue-tsc is a wrapper around tsc, TypeScript's own command line interface. It works largely the same as tsc except that it supports Vue SFCs in addition to TypeScript files. You can run vue-tsc in watch mode in parallel to the Vite dev server.

vue-tscってのがあって、これがtscのラッパーなんだと。SFCに対してはこれで型チェックができるそう。

Takeover Mode This section only applies for VSCode + Volar.

そんなのがあるんだ。VSCode強しだ。まあスキップします。

基本的な使い方

https://vuejs.org/guide/typescript/overview.html#general-usage-notes

ここから本題って感じだ。

defineComponent()

TypeScriptに対して、コンポーネント内のオプションに対して適切に型を参照させるために使用する。

サンプルみる感じだと、script setupを使用する時にはdefineComponentは必要ない。

型チェックはtemplate内に対しても実行されるみたい。


...StackBlitzでやっちゃうとIDEでやっている型チェックが走らないので意味ないじゃん 結局ローカルで環境を作り直す。

IkumaTadokoro commented 2 years ago

Composition APIにおける型定義

https://vuejs.org/guide/typescript/composition-api.html

props

script setupを使用するのが基本系。

definePropsマクロを使用したpropsの定義は

  1. runtime declaration
  2. type-based declaration

の2種類ある。

どちらを使っても良いが、使用するのはどちらか一方のみ。

一方で単純に型定義としてpropsを定義することもできる。これが一番楽なんでは。

definePropsマクロをGenericありで使用する場合(type-based declaration?)、以下の制約がある。

これはVueのコンポーネントはそれぞれ別々にコンパイルされるから。そのうち撤廃されるそう。

script setupを使用しない場合hは、defineComponentを使用する必要がある。propsの型はsetup内のpropsオプションで定義される。

emit

emitもscript setupを使用していれば、defineEmitsマクロを使用できる。

<script setup lang="ts">
// runtime
const emit = defineEmits(['change', 'update'])

// type-based
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>

ref()

import { ref } from 'vue'
import type { Ref } from 'vue'

const year: Ref<string | number> = ref('2020')

year.value = 2020 // ok!
// resulting type: Ref<string | number>
const year = ref<string | number>('2020')

year.value = 2020 // ok!

初期値が未設定で型引数をつけた場合、Ref<generic | undefined>になる

computed()

getterの戻り値から型を推論する

import { ref, computed } from 'vue'

const count = ref(0)

// inferred type: ComputedRef<number>
const double = computed(() => count.value * 2)

特定の型を型引数に指定することもできる

const double = computed<number>(() => {
  return count.value * 2
})

イベントハンドラ

ネイティブのDOMイベントを扱っている場合、ハンドラに渡す引数がを正しく定義した方がいいケースがある。

event引数は基本的に暗黙のanyを持っているのでEventを、内部的な値は適切な型アサーションを定義するのが良い。

テンプレート参照

テンプレート参照は明示的に型引数と初期値nullで定義するべき。

const el = ref<HTMLInputElement | null>(null)

コンポーネントがマウントされるまでは初期値はnullで、v-ifによって参照されている要素がアンマウントされた場合にも、nullに設定される可能性がある。

そのため、上記elの要素el.valueにアクセスするためには、オプショナルチェーンや型ガードが必要。

IkumaTadokoro commented 2 years ago

Origin解体新書を読む

有料書籍なのでキーワードだけメモ

50分で一旦リタイア。来週読みます。