React(tsx)でよくみる下記の記述
下位レベルのコンポーネント(アトミックデザインで言うatom)を定義するときいちいちpropsを再定義するのは面倒なので、もとの<button>
が持っている属性の定義をそのまま使って、受け取ったpropsをそのままスプレッド演算子で再代入する方法。
const MyButton = (props: JSX.IntrinsicElements['button']) => <button {...props} />
これVueでもできないの?
と思って調べたんですが、下記のように「ButtonHTMLAttributes」など@vueのパッケージに含まれているruntime-dom.d.ts
に定義されている型定義使うと同じように、面倒なpropsの再定義を回避することができそうです。
<template>
<button class="button" v-bind="props"><slot></slot></button>
</template>
<script setup lang="ts">
import { ButtonHTMLAttributes } from 'vue'
interface Props extends ButtonHTMLAttributes {}
const props = defineProps<Props>()
</script>
ちなみに、空のinterfaceがeslintで勝手にtypeに変換されて、vueのコンパイラに怒られるという人は以下のように@typescript-eslint/no-empty-interface
をeslintの設定に指定すると回避できました。
これが
interface Props extends ButtonHTMLAttributes {}
これに変換されて怒られる場合は
type Props = ButtonHTMLAttributes
eslintの設定をこう。
.eslintrc.js
/** @type {import("eslint").Linter.Config} */
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
'plugin:vue/vue3-recommended',
'eslint:recommended',
'@vue/typescript/recommended',
'prettier'
],
parserOptions: {
ecmaVersion: 12
},
plugins: ['vue', '@typescript-eslint'],
rules: {
'vue/multi-word-component-names': 'off',
// ここから
'@typescript-eslint/no-empty-interface': [
'error',
{
allowSingleExtends: true
}
]
// ここまで
}
}
検証浅めなので、もっと良い方法あったらコメントで教えて下さい🎍