Skip to content

Commit

Permalink
feat: autofix in define-props-declaration: runtime syntax to type-b…
Browse files Browse the repository at this point in the history
…ased syntax (vuejs#2465)

handle array of types
  • Loading branch information
mpiniarski committed May 28, 2024
1 parent 5e1d3b1 commit bc506f9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
38 changes: 22 additions & 16 deletions lib/rules/define-props-declaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const mapNativeType = (/** @type {string} */ nativeType) => {
case 'Number': {
return 'number'
}
case 'Boolean':
case 'BigInt': {
case 'Boolean': {
return 'boolean'
}
case 'Object': {
Expand All @@ -41,26 +40,19 @@ const mapNativeType = (/** @type {string} */ nativeType) => {
* @param {SourceCode} sourceCode
*/
function getComponentPropData(prop, sourceCode) {
const unknownType = {
name: prop.propName,
type: 'unknown',
required: undefined,
defaultValue: undefined
}

if (prop.type !== 'object') {
return unknownType
throw new Error(`Unexpected prop type: ${prop.type}.`)
}
const type = optionGetType(prop.value, sourceCode)
if (type === null) {
return unknownType
throw new Error(`Unexpected prop type: ${prop.type}.`)
}
const required = optionGetRequired(prop.value)
const defaultValue = optionGetDefault(prop.value)

return {
name: prop.propName,
type: mapNativeType(type),
type,
required,
defaultValue
}
Expand All @@ -74,7 +66,7 @@ function getComponentPropData(prop, sourceCode) {
function optionGetType(node, sourceCode) {
switch (node.type) {
case 'Identifier': {
return node.name
return mapNativeType(node.name)
}
case 'ObjectExpression': {
// foo: {
Expand Down Expand Up @@ -107,7 +99,17 @@ function optionGetType(node, sourceCode) {
return optionGetType(typeProperty.value, sourceCode)
}
case 'ArrayExpression': {
return null
return node.elements
.map((element) => {
// TODO handle SpreadElement
if (element === null || element.type === 'SpreadElement') {
return null
}

return optionGetType(element, sourceCode)
})
.filter(Boolean)
.join(' | ')
}
case 'FunctionExpression':
case 'ArrowFunctionExpression': {
Expand Down Expand Up @@ -217,7 +219,9 @@ module.exports = {
const definePropsType = `{ ${propTypes
.map(
({ name, type, required, defaultValue }) =>
`${name}${required === false || defaultValue ? '?' : ''}: ${type}`
`${name}${
required === false || defaultValue ? '?' : ''
}: ${type}`
)
.join(', ')} }`

Expand All @@ -227,7 +231,9 @@ module.exports = {
// add type annotation
if (separateInterface) {
const variableDeclarationNode = node.parent.parent
if (!variableDeclarationNode) return
if (!variableDeclarationNode) {
return
}

yield fixer.insertTextBefore(
variableDeclarationNode,
Expand Down
25 changes: 25 additions & 0 deletions tests/lib/rules/define-props-declaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,31 @@ tester.run('define-props-declaration', rule, {
}
]
},
// Array of types
{
only: true,
filename: 'test.vue',
code: `
<script setup lang="ts">
const props = defineProps({
kind: {
type: [String, Number]
}
})
</script>
`,
output: `
<script setup lang="ts">
const props = defineProps<{ kind: string | number }>()
</script>
`,
errors: [
{
message: 'Use type-based declaration instead of runtime declaration.',
line: 3
}
]
},
// runtime
{
filename: 'test.vue',
Expand Down

0 comments on commit bc506f9

Please sign in to comment.