Vue + TS — Props 型付け
テクノロジ系 / L06 vue-typescript — TypeScript 連携
Vue + TS — Props 型付け
基本パターン (再掲)
<script setup lang="ts">
const props = defineProps<{
name: string;
age: number;
email?: string;
}>();
</script>defineProps<{...}>() で TS の型から自動生成。
interface を別出し (推奨)
<script setup lang="ts">
interface Props {
user: User;
showActions?: boolean;
onUpdate?: (user: User) => void;
}
const props = defineProps<Props>();
</script>interface を上で定義 → 読みやすい・再利用しやすい。
外部 import
// types/user.ts
export interface User {
id: number;
name: string;
email: string;
}<script setup lang="ts">
import type { User } from "@/types/user.js";
interface Props {
user: User;
}
const props = defineProps<Props>();
</script>複数 component で共有する型は別ファイルへ。
import type で コンパイル後の JS から消える。
withDefaults
<script setup lang="ts">
interface Props {
count?: number;
label?: string;
items?: string[];
}
const props = withDefaults(defineProps<Props>(), {
count: 0,
label: "Item",
items: () => [], // 配列・objectは関数で返す
});
</script>配列やオブジェクトは 関数で返す こと (毎インスタンスで新規)。
inline 型
<script setup lang="ts">
const props = defineProps<{
onSubmit: (data: { name: string; age: number }) => Promise<void>;
}>();
</script>その component でしか使わない型ならインライン。
共有するなら interface 別出し。
TS の型 + バリデーション
実行時バリデーションも必要なら Zod:
<script setup lang="ts">
import { z } from "zod";
const UserSchema = z.object({
id: z.number(),
name: z.string(),
});
interface Props {
userJson: unknown;
}
const props = defineProps<Props>();
const user = computed(() => UserSchema.parse(props.userJson));
</script>外部 (API) から来るデータの形を保証。
まとめ
defineProps<Props>()でTS型ベース- interface 別出しで読みやすく
withDefaultsでデフォルト値、配列は関数で- 共有型は別ファイル +
import type - 実行時検証は Zod 併用
最後は Emits の型付け。
考えてみよう
既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。
Lv1: 基本 — defineProps<Props>
問題
<script setup lang="ts">
interface Props {
user: { id: number; name: string };
showActions?: boolean;
}
const props = defineProps<Props>();
</script>
<template>
<div>
<h2>{{ props.user.name }}</h2>
<button v-if="props.showActions">Edit</button>
</div>
</template>合格基準
- TS 推論で props 補完
- 不正な値の代入で型エラー
Lv2: 応用 — 共有型を別ファイル
問題
// types/user.ts
export interface User { id: number; name: string; email: string }<script setup lang="ts">
import type { User } from "@/types/user.js";
const props = defineProps<{ user: User }>();
</script>複数 component で同じ User 型を共有。
合格基準
- 型を別ファイルから import
- import type で実行時に消える
Lv3: 発展 — withDefaults
問題
<script setup lang="ts">
interface Props {
count?: number;
label?: string;
items?: string[];
}
const props = withDefaults(defineProps<Props>(), {
count: 0,
label: "Default",
items: () => [], // ← 配列は関数で返す
});
</script>
<template>
<p>{{ props.label }} ({{ props.count }})</p>
<ul><li v-for="i in props.items" :key="i">{{ i }}</li></ul>
</template>合格基準
- デフォルト値が効く
- 配列が 関数で返す 理由 (毎インスタンスで新規) を理解
提出
submission.md に3問の回答を。