1
0

Nuxt3,Vue3でのgenericsの使い方

Last updated at Posted at 2023-12-07

nuxt3, vue3からpropsにジェネリクスを使えるようになりました。
今回はNuxt3で作成します。

例として以下のような type="text", type="number"両方指定できるコンポーネントを作成します。
image.png

genericsなし

まずは、ジェネリクスなしで実装してみます。
この状態だと、emitされる値がnumberなのかstringなのか分かりません。

/components/atoms/Input.vue

<script lang="ts">
type Props = {
  inputType?: 'number' | 'text';
  value: number | string;
};

const props = withDefaults(defineProps<Props>(), { inputType: 'text' });

type Emits = {
  // props.valueの型が分からない
  (event: 'change', value: number | string): void;
};

const emits = defineEmits<Emits>();

const onChange = (event: any): void => {
  emits('change', event.target.value);
};
</script>

<template>
  <input :type="props.inputType" :value="props.value" @change="onChange" />
</template>

/pages/index.vue

<script setup lang="ts">
const strValue = ref('');
const numValue = ref(0);
</script>

<template>
  <div>
    <!--代入する際、型が分からないのでキャストしないといけない-->
    <AtomsInput :value="strValue" @change="strValue = String($event)" />
    <AtomsInput
      input-type="number"
      :value="numValue"
      @change="numValue = Number($event)"
    />
  </div>
</template>

genericsあり

scriptタグにgeneric="T extends number | string"このように指定します。
すると親コンポーネントで指定された、valueの型がTの型となります。

/components/atoms/Input.vue

<script setup lang="ts" generic="T extends number | string">
type Props = {
  inputType?: 'number' | 'text';
  value: T;
};

const props = withDefaults(defineProps<Props>(), { inputType: 'text' });

type Emits = {
  // props.valueの型によってTが変わる
  (event: 'change', value: T): void;
};

const emits = defineEmits<Emits>();

const onChange = (event: any): void => {
  emits('change', event.target.value);
};
</script>

<template>
  <input :type="props.inputType" :value="props.value" @change="onChange" />
</template>

/pages/index.vue

<script setup lang="ts">
const strValue = ref('');
const numValue = ref(0);
</script>

<template>
  <div>
    <AtomsInput :value="strValue" @change="strValue = $event" />
    <AtomsInput
      input-type="number"
      :value="numValue"
      @change="numValue = $event"
    />
  </div>
</template>

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0