PropsとEmitsに関する新機能
まず、最初に紹介するのは、新機能リストの1と2、すなわち、PropsとEmitsに関する新機能です。
Props型定義とEmits型定義のインポート
Vueのコンポーネント間連携であるPropsとEmitを利用する際、defineProps()とdefineEmits()マクロを利用します。その際、ジェネリクスとして、Propsならば個々のPropを型定義したものを、Emitならば関数の型定義を渡します。
この型定義に関して、これまではリスト1のように、defineProps()やdefineEmits()を実行するコンポーネント内で定義したもの、つまり、ローカルな型定義である必要がありました。
interface Props {
id: number;
name: string;
email: string;
points: number;
}
interface Emits {
(event: "incrementPoint", id: number): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
これが、Vue3.3では、リスト2のように、別ファイルに記述した型定義をインポートして利用できるようになりました。これにより、PropsとEmitの型定義の再利用が可能となります。
import type {Props, Emits} from "@/interfacesForMacros";
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
[NOTE]マクロ
defineProps()やdefineEmits()関数は、通常の関数とは違い、「マクロ」と呼ばれています。マクロとは、ソースコードがコンパイルされる際に別の関数などを生成することで、コンパイル後には存在しなくなる特殊な関数のことです。
新しいEmits定義
このようにインポートできるようになったマクロ用の型定義に関して、Emitについては、さらに新しい仕組みが導入されました。これまでは、リスト2のインターフェースEmitsのように、コールシグネチャを記述する必要がありました。
Vue3.3では、このコールシグネチャももちろん利用できますが、新たな型定義が導入されました。これは、リスト3のようになります。
type Emits = {
incrementPoint: [id: number];
};
これまでのコールシグネチャでは引数eventのリテラル型としていたイベント名を、プロパティ名としたオブジェクトを定義します。そのプロパティの値として、これまでのコールシグネチャの第2引数以降として記述していた部分、すなわち、Emit関数の実行時に親コンポーネントにデータを渡すための引数定義をラベル付きタプルとして記述します。
もし、引数の不要なEmit定義の場合は、リスト4のように空の配列定義とします。
type Emits = {
incrementPoint: [];
};
なお、このラベル付きタプルを利用した新しいEmitsの型定義については、インターフェースとして定義するとエラーとなります。そのため、リスト3やリスト4のように、typeキーワードを利用した型定義とします。
[NOTE]ラベル付きタプル
通常、TypeScriptのタプルは、以下のように配列の各要素に対してデータ型のみを定義します。
type BMIData = [string, number, number];
この各要素のデータ型に、以下のように、さらに変数名のようにラベルをつけることができます。これを「ラベル付きタプル」といいます。
type BMIData = [name: string, height: number, weight: number];
インポートした型定義の拡張も可能
このPropsやEmitsのマクロ用の型定義に関しては、インポートした型を拡張して利用することも、Vue3.3で可能となりました。例えば、リスト5のようなコードです。
import type {Props as PropsOrgn, Emits} from "@/interfacesForMacros"; // (1)
interface Props extends PropsOrgn { // (2)
note?: string; // (3)
}
const props = defineProps<Props>();
リスト4との違いは、interfacesForMacros.tsからインポートしたインターフェースPropsをPropsOrgnとし、(2)でそのPropsOrgnを拡張したインターフェースPropsを定義し、(3)のnoteプロパティを追加しています。
