mirror of https://github.com/vuejs/core.git
feat(compiler-sfc): improve runtime props inference for enum
This commit is contained in:
parent
5fb406e3e1
commit
eded94712e
|
@ -1573,6 +1573,56 @@ const emit = defineEmits(['a', 'b'])
|
|||
})
|
||||
})
|
||||
|
||||
test('runtime inference for Enum in defineProps', () => {
|
||||
expect(
|
||||
compile(
|
||||
`<script setup lang="ts">
|
||||
const enum Foo { A = 123 }
|
||||
defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
).toMatch(`foo: { type: Number`)
|
||||
|
||||
expect(
|
||||
compile(
|
||||
`<script setup lang="ts">
|
||||
const enum Foo { A = '123' }
|
||||
defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
).toMatch(`foo: { type: String`)
|
||||
|
||||
expect(
|
||||
compile(
|
||||
`<script setup lang="ts">
|
||||
const enum Foo { A = '123', B = 123 }
|
||||
defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
).toMatch(`foo: { type: [String, Number]`)
|
||||
|
||||
expect(
|
||||
compile(
|
||||
`<script setup lang="ts">
|
||||
const enum Foo { A, B }
|
||||
defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
).toMatch(`foo: { type: Number`)
|
||||
})
|
||||
|
||||
test('import type', () => {
|
||||
const { content } = compile(
|
||||
`<script setup lang="ts">
|
||||
|
|
|
@ -44,7 +44,8 @@ import {
|
|||
ObjectMethod,
|
||||
LVal,
|
||||
Expression,
|
||||
VariableDeclaration
|
||||
VariableDeclaration,
|
||||
TSEnumDeclaration
|
||||
} from '@babel/types'
|
||||
import { walk } from 'estree-walker'
|
||||
import { RawSourceMap } from 'source-map'
|
||||
|
@ -1369,14 +1370,15 @@ export function compileScript(
|
|||
if (isTS) {
|
||||
// move all Type declarations to outer scope
|
||||
if (
|
||||
(node.type.startsWith('TS') ||
|
||||
(node.type === 'ExportNamedDeclaration' &&
|
||||
node.exportKind === 'type') ||
|
||||
(node.type === 'VariableDeclaration' && node.declare)) &&
|
||||
node.type !== 'TSEnumDeclaration'
|
||||
node.type.startsWith('TS') ||
|
||||
(node.type === 'ExportNamedDeclaration' &&
|
||||
node.exportKind === 'type') ||
|
||||
(node.type === 'VariableDeclaration' && node.declare)
|
||||
) {
|
||||
recordType(node, declaredTypes)
|
||||
hoistNode(node)
|
||||
if (node.type !== 'TSEnumDeclaration') {
|
||||
hoistNode(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1966,6 +1968,8 @@ function recordType(node: Node, declaredTypes: Record<string, string[]>) {
|
|||
)
|
||||
} else if (node.type === 'ExportNamedDeclaration' && node.declaration) {
|
||||
recordType(node.declaration, declaredTypes)
|
||||
} else if (node.type === 'TSEnumDeclaration') {
|
||||
declaredTypes[node.id.name] = inferEnumType(node)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2152,6 +2156,23 @@ function toRuntimeTypeString(types: string[]) {
|
|||
return types.length > 1 ? `[${types.join(', ')}]` : types[0]
|
||||
}
|
||||
|
||||
function inferEnumType(node: TSEnumDeclaration): string[] {
|
||||
const types = new Set<string>()
|
||||
for (const m of node.members) {
|
||||
if (m.initializer) {
|
||||
switch (m.initializer.type) {
|
||||
case 'StringLiteral':
|
||||
types.add('String')
|
||||
break
|
||||
case 'NumericLiteral':
|
||||
types.add('Number')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.size ? [...types] : ['Number']
|
||||
}
|
||||
|
||||
function extractRuntimeEmits(
|
||||
node: TSFunctionType | TSTypeLiteral | TSInterfaceBody,
|
||||
emits: Set<string>
|
||||
|
|
Loading…
Reference in New Issue