0.0.12 • Published 4 years ago

@icare-jp/vue-props-story-fn-factory v0.0.12

Weekly downloads
160
License
MIT
Repository
github
Last release
4 years ago

Vue Props Type

Vue Props TypeVue.jspropsの型定義を助けます.

Why

composition-apiを利用したコードを書く場合、以下のように書く必要があります.

import { defineComponent } from '@vue/composition-api'

export type HogeHogeProps = {
  A: 'github' | 'qiita' | 'facebook'
  B: 0 | 1 | Date
  C: { label: string, value: string }
  D: string[]
  E: string | number
  F: (key: string, value: string) => void
}

export default defineComponent<HogeHogeProps>({
  name: 'HogeHoge',
  props: {
    A: {
      type: String,
      default: () => 'github'
    },
    B: {
      type: [Number, Date],
      required: true,
    },
    C: {
      type: Object,
      required: true,
    },
    D: {
      type: Array,
      required: true,
    },
    E: [String, Number],
    F: Function,
  },
  setup(props) {
    // props is type safe
  },
})

Optionに渡すprops objectと型定義のProps typeは別々で定義されおり、素直に書く場合は、人の手により両方をメンテナンスする必用があります. これには課題があり、もしprops objectのコードを変更し、Props typeの修正を忘れた場合、HogeHogeProps type又はprops objectは嘘をつくことになります. 人によってはprops objectの項目が多い場合、Props typeの型定義をサボりたくなるでしょう. 人によってはsetup内でアクセスしているprops objectの項目の型定義しか書かない可能性もあります. 以下がその例です.

import { defineComponent } from '@vue/composition-api'

export type HogeHogeProps = {
  A: 'github' | 'qiita' | 'facebook'
}

export default defineComponent<HogeHogeProps>({
  name: 'HogeHoge',
  props: {
    A: {
      type: String,
      default: () => 'github'
    },
    B: {
      type: [Number, Date],
      required: true,
    },
    C: {
      type: Object,
      required: true,
    },
    D: {
      type: Array,
      required: true,
    },
    E: [String, Number],
    F: Function,
  },
  setup(props) {
    // Props type is { A: string }
    console.log(props.A)
  },
})

しかもこの例では少なくともDEFがどんな模様の型なのか一切わかりません. templateの中でどのようにアクセスされているのでしょうか? 我々がその模様を知りたい場合、そこから読み解く必用があります. 我々の気合による推論で消費する時間は多いのに対して、型定義でサボって得られる時間はごくわずかです. しかも我々の推論結果が実装者の意図とただしくない可能性があります.

また、サボった場合は、Typescriptのエコシステムの恩恵を正しく受けれなくなるリスクがあります. (例: templateの型検査等 Vue Props TypeはTypeScriptの力によって、このような課題の解決をシンプル且つ簡単に解決することを目指します. 以下がVue Props Typeを使ったサンプルです.

import { defineComponent } from '@vue/composition-api'
import { InsidePropsType, OutsidePropsType, PropType } from '@icare-jp/vue-props-type'

const propsType = {
  A: {
    type: String as PropType<'github' | 'qiita' | 'facebook'>,
    default: () => 'github'
  },
  B: {
    type: [Number, Date] as PropType<0 | 1 | Date>,
    required: true,
  },
  C: {
    type: Object as PropType<{ label: string, value: string }>,
    required: true,
  },
  D: {
    type: Array as PropType<string[]>,
    required: true,
  },
  E: [String, Number],
  F: Function as (key: string, value: string) => void
} as const

export type HogeHogeProps = OutsidePropsType<typeof propsType>
// {
//   A?: string | undefined;
//   B: 0 | Date | 1;
//   C: Readonly<{
//     label: string;
//     value: string;
//   }>;
//   D: string[];
//   E?: string | number | undefined;
//   F?: ((key: string, value: string) => void) | undefined;
// }

type InsideHogeHogeProps = InsidePropsType<typeof propsType>
// {
//   readonly A: string;
//   readonly B: 0 | Date | 1;
//   readonly C: Readonly<{
//     label: string;
//     value: string;
//   }>;
//   readonly D: readonly string[];
//   readonly E: string | number | undefined;
//   readonly F: ((key: string, value: string) => void) | undefined;
// }

export default defineComponent<InsideHogeHogeProps>({
  name: 'HogeHoge',
  props: propsType,
  setup(props) {
    // props is type safe
  },
})

InsidePropsType を使う事により、 props の管理を楽にし、型定義を書くストレスを軽減します. また、 Vue.jsprops へ変更を加える操作を禁止しています. そのため、 props を標準で readonly にしています. もし readonly にすることにより何かしらの問題が起こる場合は UnsafePropsType を利用してください. また、 required: truedefault: () => any も無い場合、 undefined を混ぜています. また、 default: () => any がある場合は戻り値を抽出し、混ぜています. それにより、より実行結果に近い、つまり真実に近い型を得られます.

また、用意されたコンポーネントを利用する側がtype safeにpropsを用意したい場合、以下のようなコードを手動で書き、用意しなければなりません.

export type HogeHogeProps = {
  A?: string | undefined;
  B: 0 | Date | 1;
  C: Readonly<{
    label: string;
    value: string;
  }>;
  D: string[];
  E?: string | number | undefined;
  F?: ((key: string, value: string) => void) | undefined;
}

InsideHogeHogePropsと全く同じ様にOutsidePropsTypeを利用すれば、この型を自動で生成でき、型定義を書くストレスを軽減します. 些細な意見でも結構ですので、なにかありましたら気軽にissueを立てて申し立ててくださると幸いです.

0.0.11

4 years ago

0.0.12

4 years ago

0.0.10

4 years ago

0.0.9

4 years ago

0.0.8

4 years ago

0.0.5

4 years ago

0.0.7

4 years ago

0.0.6

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago