Skip to content

Instantly share code, notes, and snippets.

@wonderful-panda
Created June 26, 2019 03:33
Show Gist options
  • Save wonderful-panda/2661c031327ca02c91274fd70a991928 to your computer and use it in GitHub Desktop.
Save wonderful-panda/2661c031327ca02c91274fd70a991928 to your computer and use it in GitHub Desktop.
vue-class-component + vue-property-decorator で作ったコンポーネントをなるべくストレスなくTSXで使いたい

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>;
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment