script setup: expected TypeScript type by compiler for defineEmit is not useful
Version
3.0.4
Reproduction link
Steps to reproduce
const emit = defineEmit<SOME_TYPE_HERE>();
emit('foo');
emit('bar');
emit('baz', 1);
What is expected?
Should be able to specify SOME_TYPE_HERE correctly so the resulting program has no TypeScript error and no error from vue compiler.
What is actually happening?
SOME_TYPE_HERE = ((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)
=> TypeScript errorSOME_TYPE_HERE = {(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}
=> vue compiler error
[@vue/compiler-sfc] type argument passed to defineEmit() must be a function type or a union of function types.
Currently the type expected for defineEmit is a function type or union type, but the type ((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)
is actually not useful as a emit function, as can be seen in the above TypeScript playground, since the type ((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)
is equivalent to ((e: never, id: number) => void)
.
The correct way to specifies this seems to be using call signature {(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}
.
((e: 'foo' | 'bar') => void) & ((e: 'baz', id: number) => void)
also works for TypeScript, but vue compiler reject this too.
With an interface I also gen a compiler Error:
interface Emit {
(e: 'delete', id: string): void;
(e: 'duplicate', id: string): void;
(e: 'start', id: string): void;
}
const emit = defineEmit<Emit>();
Syntax Error: TypeError: Cannot read property 'content' of null
But the types ware correct. Any solutions to this? :)