Often I find that I'm copying prop types from a child component just to use them in a parent component. But I've discovered that stealing those prop types is much better than just copying them.
For example, we have an Icon
component being used in this component:
<template><div><h2>{{ heading }}</h2><Icon:type="iconType":size="iconSize":colour="iconColour"/></div></template>
To get this to work, we need to add the correct prop types, copying from the Icon
component:
import Icon from './Icon';export default {components: { Icon },props: {iconType: {type: String,required: true,},iconSize: {type: String,default: 'medium',validator: size => ['small','medium','large','x-large'].includes(size),},iconColour: {type: String,default: 'black',},heading: {type: String,required: true,},},};
What a pain.
And when the prop types of the Icon
component are updated, you can be sure that you'll forget to return to this component and update them. Over time bugs will be introduced as the prop types for this component start to drift away from the prop types in the Icon
component.
So that's why we'll steal them instead:
import Icon from './Icon';export default {components: { Icon },props: {...Icon.props,heading: {type: String,required: true,},},};
It doesn't have to get any more complicated than that!
Except in our example, we have an "icon" added to the beginning of each prop name. So we'll have to do some extra work to get that to happen:
import Icon from './Icon';const iconProps = {};// Do some processing beforehandObject.entries(Icon.props).forEach((key, val) => {iconProps[`icon${key[0].toUpperCase()}${key.substring(1)}`] = val;});export default {components: { Icon },props: {...iconProps,heading: {type: String,required: true,},},};
If the prop types in the Icon
component are modified, our component will stay up-to-date.
But what if a prop type is added or removed from the Icon
component? We can use v-bind
and a computed prop to keep things dynamic and cover those cases.