Skip to content

Commit

Permalink
feat(compiler-sfc): improve runtime props inference for enum
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Mar 28, 2023
1 parent 5fb406e commit eded947
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 7 deletions.
50 changes: 50 additions & 0 deletions packages/compiler-sfc/__tests__/compileScript.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
35 changes: 28 additions & 7 deletions packages/compiler-sfc/src/compileScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import {
ObjectMethod,
LVal,
Expression,
VariableDeclaration
VariableDeclaration,
TSEnumDeclaration
} from '@babel/types'
import { walk } from 'estree-walker'
import { RawSourceMap } from 'source-map'
Expand Down Expand Up @@ -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)
}
}
}
}
Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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>
Expand Down

0 comments on commit eded947

Please sign in to comment.