Skip to content

Commit ef73ea5

Browse files
committed
feat(compiler-sfc): codegen support for defineEmits() short syntax (followup of #7992)
1 parent 8876dcc commit ef73ea5

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

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

+16
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,22 @@ export default /*#__PURE__*/_defineComponent({
14781478

14791479

14801480

1481+
return { emit }
1482+
}
1483+
1484+
})"
1485+
`;
1486+
1487+
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (tuple syntax) 1`] = `
1488+
"import { defineComponent as _defineComponent } from 'vue'
1489+
1490+
export default /*#__PURE__*/_defineComponent({
1491+
emits: [\\"foo\\", \\"bar\\"],
1492+
setup(__props, { expose: __expose, emit }: { emit: ({ foo: [], bar: [] }), expose: any, slots: any, attrs: any }) {
1493+
__expose();
1494+
1495+
1496+
14811497
return { emit }
14821498
}
14831499

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

+23
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,16 @@ const emit = defineEmits(['a', 'b'])
15401540
expect(content).toMatch(`emits: ['foo']`)
15411541
})
15421542

1543+
test('defineEmits w/ type (tuple syntax)', () => {
1544+
const { content } = compile(`
1545+
<script setup lang="ts">
1546+
const emit = defineEmits<{ foo: [], bar: [] }>()
1547+
</script>
1548+
`)
1549+
expect(content).toMatch(`emits: ["foo", "bar"]`)
1550+
assertCode(content)
1551+
})
1552+
15431553
test('runtime Enum', () => {
15441554
const { content, bindings } = compile(
15451555
`<script setup lang="ts">
@@ -1871,6 +1881,19 @@ const emit = defineEmits(['a', 'b'])
18711881
</script>`).content
18721882
)
18731883
})
1884+
1885+
test('mixed usage of tuple / call signature in defineEmits', () => {
1886+
expect(() =>
1887+
compile(`<script setup lang="ts">
1888+
defineEmits<{
1889+
foo: []
1890+
(e: 'hi'): void
1891+
}>()
1892+
</script>`)
1893+
).toThrow(
1894+
`defineEmits() type cannot mixed call signature and property syntax.`
1895+
)
1896+
})
18741897
})
18751898
})
18761899

packages/compiler-sfc/src/compileScript.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,7 @@ export function compileScript(
14861486
extractRuntimeProps(propsTypeDecl, typeDeclaredProps, declaredTypes)
14871487
}
14881488
if (emitsTypeDecl) {
1489-
extractRuntimeEmits(emitsTypeDecl, typeDeclaredEmits)
1489+
extractRuntimeEmits(emitsTypeDecl, typeDeclaredEmits, error)
14901490
}
14911491

14921492
// 5. check macro args to make sure it doesn't reference setup scope
@@ -2289,15 +2289,32 @@ function inferValueType(node: Node): string | undefined {
22892289

22902290
function extractRuntimeEmits(
22912291
node: TSFunctionType | TSTypeLiteral | TSInterfaceBody,
2292-
emits: Set<string>
2292+
emits: Set<string>,
2293+
error: (msg: string, node: Node) => never
22932294
) {
22942295
if (node.type === 'TSTypeLiteral' || node.type === 'TSInterfaceBody') {
22952296
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
2297+
let hasCallSignature = false
2298+
let hasProperty = false
22962299
for (let t of members) {
22972300
if (t.type === 'TSCallSignatureDeclaration') {
22982301
extractEventNames(t.parameters[0], emits)
2302+
hasCallSignature = true
2303+
}
2304+
if (t.type === 'TSPropertySignature') {
2305+
if (t.key.type !== 'Identifier' || t.computed) {
2306+
error(`defineEmits() type cannot use computed keys.`, t.key)
2307+
}
2308+
emits.add(t.key.name)
2309+
hasProperty = true
22992310
}
23002311
}
2312+
if (hasCallSignature && hasProperty) {
2313+
error(
2314+
`defineEmits() type cannot mixed call signature and property syntax.`,
2315+
node
2316+
)
2317+
}
23012318
return
23022319
} else {
23032320
extractEventNames(node.parameters[0], emits)

0 commit comments

Comments
 (0)