Skip to content

Commit bc506f9

Browse files
committed
feat: autofix in define-props-declaration: runtime syntax to type-based syntax (#2465)
handle array of types
1 parent 5e1d3b1 commit bc506f9

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

lib/rules/define-props-declaration.js

+22-16
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ const mapNativeType = (/** @type {string} */ nativeType) => {
1414
case 'Number': {
1515
return 'number'
1616
}
17-
case 'Boolean':
18-
case 'BigInt': {
17+
case 'Boolean': {
1918
return 'boolean'
2019
}
2120
case 'Object': {
@@ -41,26 +40,19 @@ const mapNativeType = (/** @type {string} */ nativeType) => {
4140
* @param {SourceCode} sourceCode
4241
*/
4342
function getComponentPropData(prop, sourceCode) {
44-
const unknownType = {
45-
name: prop.propName,
46-
type: 'unknown',
47-
required: undefined,
48-
defaultValue: undefined
49-
}
50-
5143
if (prop.type !== 'object') {
52-
return unknownType
44+
throw new Error(`Unexpected prop type: ${prop.type}.`)
5345
}
5446
const type = optionGetType(prop.value, sourceCode)
5547
if (type === null) {
56-
return unknownType
48+
throw new Error(`Unexpected prop type: ${prop.type}.`)
5749
}
5850
const required = optionGetRequired(prop.value)
5951
const defaultValue = optionGetDefault(prop.value)
6052

6153
return {
6254
name: prop.propName,
63-
type: mapNativeType(type),
55+
type,
6456
required,
6557
defaultValue
6658
}
@@ -74,7 +66,7 @@ function getComponentPropData(prop, sourceCode) {
7466
function optionGetType(node, sourceCode) {
7567
switch (node.type) {
7668
case 'Identifier': {
77-
return node.name
69+
return mapNativeType(node.name)
7870
}
7971
case 'ObjectExpression': {
8072
// foo: {
@@ -107,7 +99,17 @@ function optionGetType(node, sourceCode) {
10799
return optionGetType(typeProperty.value, sourceCode)
108100
}
109101
case 'ArrayExpression': {
110-
return null
102+
return node.elements
103+
.map((element) => {
104+
// TODO handle SpreadElement
105+
if (element === null || element.type === 'SpreadElement') {
106+
return null
107+
}
108+
109+
return optionGetType(element, sourceCode)
110+
})
111+
.filter(Boolean)
112+
.join(' | ')
111113
}
112114
case 'FunctionExpression':
113115
case 'ArrowFunctionExpression': {
@@ -217,7 +219,9 @@ module.exports = {
217219
const definePropsType = `{ ${propTypes
218220
.map(
219221
({ name, type, required, defaultValue }) =>
220-
`${name}${required === false || defaultValue ? '?' : ''}: ${type}`
222+
`${name}${
223+
required === false || defaultValue ? '?' : ''
224+
}: ${type}`
221225
)
222226
.join(', ')} }`
223227

@@ -227,7 +231,9 @@ module.exports = {
227231
// add type annotation
228232
if (separateInterface) {
229233
const variableDeclarationNode = node.parent.parent
230-
if (!variableDeclarationNode) return
234+
if (!variableDeclarationNode) {
235+
return
236+
}
231237

232238
yield fixer.insertTextBefore(
233239
variableDeclarationNode,

tests/lib/rules/define-props-declaration.js

+25
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,31 @@ tester.run('define-props-declaration', rule, {
564564
}
565565
]
566566
},
567+
// Array of types
568+
{
569+
only: true,
570+
filename: 'test.vue',
571+
code: `
572+
<script setup lang="ts">
573+
const props = defineProps({
574+
kind: {
575+
type: [String, Number]
576+
}
577+
})
578+
</script>
579+
`,
580+
output: `
581+
<script setup lang="ts">
582+
const props = defineProps<{ kind: string | number }>()
583+
</script>
584+
`,
585+
errors: [
586+
{
587+
message: 'Use type-based declaration instead of runtime declaration.',
588+
line: 3
589+
}
590+
]
591+
},
567592
// runtime
568593
{
569594
filename: 'test.vue',

0 commit comments

Comments
 (0)