Skip to content

Commit eded947

Browse files
committed
feat(compiler-sfc): improve runtime props inference for enum
1 parent 5fb406e commit eded947

File tree

2 files changed

+78
-7
lines changed

2 files changed

+78
-7
lines changed

packages/compiler-sfc/__tests__/compileScript.spec.ts

+50
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,56 @@ const emit = defineEmits(['a', 'b'])
15731573
})
15741574
})
15751575

1576+
test('runtime inference for Enum in defineProps', () => {
1577+
expect(
1578+
compile(
1579+
`<script setup lang="ts">
1580+
const enum Foo { A = 123 }
1581+
defineProps<{
1582+
foo: Foo
1583+
}>()
1584+
</script>`,
1585+
{ hoistStatic: true }
1586+
).content
1587+
).toMatch(`foo: { type: Number`)
1588+
1589+
expect(
1590+
compile(
1591+
`<script setup lang="ts">
1592+
const enum Foo { A = '123' }
1593+
defineProps<{
1594+
foo: Foo
1595+
}>()
1596+
</script>`,
1597+
{ hoistStatic: true }
1598+
).content
1599+
).toMatch(`foo: { type: String`)
1600+
1601+
expect(
1602+
compile(
1603+
`<script setup lang="ts">
1604+
const enum Foo { A = '123', B = 123 }
1605+
defineProps<{
1606+
foo: Foo
1607+
}>()
1608+
</script>`,
1609+
{ hoistStatic: true }
1610+
).content
1611+
).toMatch(`foo: { type: [String, Number]`)
1612+
1613+
expect(
1614+
compile(
1615+
`<script setup lang="ts">
1616+
const enum Foo { A, B }
1617+
defineProps<{
1618+
foo: Foo
1619+
}>()
1620+
</script>`,
1621+
{ hoistStatic: true }
1622+
).content
1623+
).toMatch(`foo: { type: Number`)
1624+
})
1625+
15761626
test('import type', () => {
15771627
const { content } = compile(
15781628
`<script setup lang="ts">

packages/compiler-sfc/src/compileScript.ts

+28-7
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ import {
4444
ObjectMethod,
4545
LVal,
4646
Expression,
47-
VariableDeclaration
47+
VariableDeclaration,
48+
TSEnumDeclaration
4849
} from '@babel/types'
4950
import { walk } from 'estree-walker'
5051
import { RawSourceMap } from 'source-map'
@@ -1369,14 +1370,15 @@ export function compileScript(
13691370
if (isTS) {
13701371
// move all Type declarations to outer scope
13711372
if (
1372-
(node.type.startsWith('TS') ||
1373-
(node.type === 'ExportNamedDeclaration' &&
1374-
node.exportKind === 'type') ||
1375-
(node.type === 'VariableDeclaration' && node.declare)) &&
1376-
node.type !== 'TSEnumDeclaration'
1373+
node.type.startsWith('TS') ||
1374+
(node.type === 'ExportNamedDeclaration' &&
1375+
node.exportKind === 'type') ||
1376+
(node.type === 'VariableDeclaration' && node.declare)
13771377
) {
13781378
recordType(node, declaredTypes)
1379-
hoistNode(node)
1379+
if (node.type !== 'TSEnumDeclaration') {
1380+
hoistNode(node)
1381+
}
13801382
}
13811383
}
13821384
}
@@ -1966,6 +1968,8 @@ function recordType(node: Node, declaredTypes: Record<string, string[]>) {
19661968
)
19671969
} else if (node.type === 'ExportNamedDeclaration' && node.declaration) {
19681970
recordType(node.declaration, declaredTypes)
1971+
} else if (node.type === 'TSEnumDeclaration') {
1972+
declaredTypes[node.id.name] = inferEnumType(node)
19691973
}
19701974
}
19711975

@@ -2152,6 +2156,23 @@ function toRuntimeTypeString(types: string[]) {
21522156
return types.length > 1 ? `[${types.join(', ')}]` : types[0]
21532157
}
21542158

2159+
function inferEnumType(node: TSEnumDeclaration): string[] {
2160+
const types = new Set<string>()
2161+
for (const m of node.members) {
2162+
if (m.initializer) {
2163+
switch (m.initializer.type) {
2164+
case 'StringLiteral':
2165+
types.add('String')
2166+
break
2167+
case 'NumericLiteral':
2168+
types.add('Number')
2169+
break
2170+
}
2171+
}
2172+
}
2173+
return types.size ? [...types] : ['Number']
2174+
}
2175+
21552176
function extractRuntimeEmits(
21562177
node: TSFunctionType | TSTypeLiteral | TSInterfaceBody,
21572178
emits: Set<string>

0 commit comments

Comments
 (0)