vue-class-component + vue-property-decorator で作ったコンポーネントをなるべくストレスなくTSXで使うための仕組みを考えていて、 vue-tsx-supportにこんな感じのHelperを追加しようかと検討中
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { DefineProps, TsxEvent, InnerScopedSlot } from "vue-tsx-support";
@Component
class MyComponent extends Vue {
// どのフィールドがTSXで指定できる属性なのかをstaticメンバの型として記述する
static TsxProps: DefineTsxProps<
MyComponent,
// foo, barをTSXの属性として指定。フィールドの定義(foo!, bar?) に従って、fooは必須、barは省略可能な属性として扱われる
"foo" | "bar",
// baz, onCustomEventをTSXの属性として指定。こちらに指定したものはフィールドの定義にかかわらず省略可能な属性として扱われる
"baz" | "onCustomEvent"
>;
@Prop({ type: String, required: true }) foo!: string;
@Prop(Number) bar?: number;
@Prop({ type: String, default: "defaultValue" }) baz!: string;
bra!: number;
/** @Emit("customEvent") onCustomEvent() {} と同じ。onCustomEvent()をコールすると"customEvent"がemitされる */
@TsxEvent onCustomEvent(_arg: { foo: string }) {}
// $scopedSlotsに下の要領で型付けすることによって、自身のrender内で型安全にアクセスできるようになると同時に、
// 親コンポーネントからscopedSlotsが指定する時にもスロット名や引数の型がチェックされるようになる
$scopedSlots!: {
default: InnerScopedSlot<{ ssprops: string }>;
optional?: InnerScopedSlot<string>;
}
}