0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Composition APIにおいて、JavaScriptからTypeScriptにして変わったこと

Last updated at Posted at 2023-04-09

概要

JavaScriptで書かれたコードをTypeScriptに移行したので、そのときに書き換えた部分をメモします。

変わったこと

setupの書き方

JavaScript

ファイルを新規作成するたびにこれを書くのが大変でした。エディタが自動で書いてくれることもありますが、どちらにせよインデントが増えるので面倒です。

<script>
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
  setup() {
    // 処理
  },
});
</script>

TypeScript

書き方が非常にシンプルになりました。スッキリしてますね。

<script setup lang="ts">
// 処理
</script>

propsの書き方

見やすくはあるのですが、一つのプロパティに4・5行使うのは少し鬱陶しいですね。

JavaScript

<script>
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
  props: {
    message: {
      type: String,
      required: true,
      default: 'Hello World',
    },
    count : {
      type: Number,
      required: false,
      default: 1,
    },
    names: {
      type: Array,
      required: false,
    },
  },
  setup() {
    // 処理
  },
});
</script>

TypeScript

一つのプロパティが1行で済むので助かります。ただ、初期値を設定する場合はJavaScriptより少し面倒かもしれません。

<script setup lang="ts">
// 初期値を設定しない場合
const props = defineProps<{
  message: string;
  count?: number;
  names?: string[];
}>();
</script>
<script setup lang="ts">
// 初期値を設定する場合
export interface Props {
  message: string;
  count?: number;
  names?: string[];
}
const props = withDefaults(defineProps<Props>(), {
  message: 'Hello World',
  count: 1,
  names: () => [],
});
</script>

[追記]
ESLintを利用している場合、上のコードだと'props' is assigned a value but never usedというエラーが出てしまいます。scriptタグ内でpropsを利用せずtemplateタグのみで利用する場合は、const propsを省略して次のような書き方で大丈夫です。

<script setup lang="ts">
defineProps<{
  message: string;
  count?: number;
  names?: string[];
}>();
</script>

変数・関数の扱い

JavaScript

毎回returnに値を書いていくのが面倒ですね。

<script>
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
  setup() {
    const message = ref('');

    function changeMessage(newMessage) {
      message.value = newMessage;
    }

    return {
      message,
      changeMessage,
    }
  },
});
</script>

TypeScript

returnが必要なくなりスッキリしました。また、関数の引数や戻り値、refなどで型指定できるのも良いですね。

<script setup lang="ts">
const message = ref<string>('');
function changeMessage(newMessage: string) {
  message.value = newMessage;
}
</script>

emitの扱い

JavaScript

setup()の引数にemitが入るのが少し気持ち悪いですね。

子コンポーネント
ChildComponent.vue
<script>
import { defineComponent } from '@vue/composition-api';

export default defineComponent({
  setup(props, { emit }) {
    function showMessage() {
      emit('showMessage', 'HelloWorld');
    }

    return {
      showMessage,
    };
  },
});
</script>

<template>
  <button @click="showMessage">
    ボタン
  </button>
</template>
親コンポーネント
ParentComponent.vue
<script>
import { defineComponent, ref } from '@vue/composition-api';

export default defineComponent({
  setup(props) {
    const message = ref('');
    function showMessage(newMessage) {
      message.value = newMessage;
    }

    return {
      message,
      showMessage,
    };
  },
});
</script>

<template>
  <p>{{ message }}</p>
  <child-component @showMessage="showMessage" />
</template>

TypeScript

emitsを独立して宣言できるようになりました。

子コンポーネント
ChildComponent.vue
<script setup lang="ts">
const emits = defineEmits<{
  (e: 'showMessage', message: string): void;
}>();
function showMessage() {
  emits('showMessage', 'HelloWorld');
}
</script>

<template>
  <button @click="showMessage">
    ボタン
  </button>
</template>
親コンポーネント
ParentComponent.vue
<script setup lang="ts">
const message = ref<string>('');
function showMessage(newMessage: string) {
  message.value = newMessage;
}
</script>

<template>
  <p>{{ message }}</p>
  <child-component @showMessage="showMessage" />
</template>

eventの扱い

JavaScript

<script>
import { defineComponent, ref } from '@vue/composition-api';

export default defineComponent({
    // 省略
    setup(props) {
    function updateValue(event) {
      emits('update:modelValue', event.target.value);
    }
    // 省略
  },
});
</script>

TypeScript

これに関してはTypeScript側が面倒ですね。型指定の弊害として受け入れるしかないのですが…。

<script setup lang="ts">
// 省略
function updateValue(event: Event): void {
  if (event.target instanceof HTMLInputElement) {
    emits('update:modelValue', event.target.value);
  }
}
</script>

終わりに

結論としては、一部面倒になったところもありますが全体としてはTypeScriptの方がスッキリ書け、型も安全になりました。他にもあったら追記していきます。

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?