TypeScript does not infer SetupContext properly
Version
3.0.0
Reproduction link
Steps to reproduce
When the instance option emits
is used with arrow-function validators (or in its simple array form), TypeScript fails to infer SetupContext<Record<string, any>>
and instead infers SetupContext<{"update:modelValue": () => true}>
(see the attached codesandbox example).
What is expected?
That I can just typehint { emit }: SetupContext
in my composable.
What is actually happening?
I need to update type definition whenever I add an emits
(or use "full" functions which is ugly).
(what you're looking for in the codesandbox is a TypeScript error. If you don't see one, wait a couple of seconds, usually it becomes visible after 15-20sec on the website - the context
variable is underlined in red.)
I don't know if this is the right place to report. If this is not a bug but deliberate, please let me know. Thanks
Looks like this might be related, will investigate later https://github.com/vuejs/vue-next/issues/2474
I think this behavior is correct because this update:modelValue
indicates that it does not receive any parameters.
https://github.com/vuejs/rfcs/blob/master/active-rfcs/0030-emits-option.md#type-inference
emits: {
'update:modelValue': function works() { return true; },
},
I think this should also infer SetupContext<{"update:modelValue": () => true}>
.
Maybe #2362 is related?
emits: {
'update:modelValue'() { return true; },
},
This may work for now. (though I think this also should infer SetupContext<{"update:modelValue": () => true}>
)
@sapphi-red - if you are right and we should be inferring SetupContext<{"update:modelValue": () => true}>
, how can I then type-hint the context
properly?
All I wanted to do in my coposable is
function myFn({ emit }: SetupContext) {
emit('sth', ...);
}
so that TypeScript (and in turn PHPStorm) infered the function signature for the emit
function.
However, if I have to revisit the type hint every time I add a new emits
, that sounds like I am not getting something about TypeScript... sorry, quite a TS newbie here 🤷
I think you should change it to SetupContext<any>
if you want to be able to emit any event.
function myFn({ emit }: SetupContext<any>) {
emit('sth', ...);
}
If you want to limit it to 'sth' event, do it like below.
function myFn({ emit }: SetupContext<{ sth: (params: any) => any }>) {
emit('sth', ...);
}
I think there is no way to infer SetupContext type from the usage of emit
.
I think there is no way to infer SetupContext type from the usage of emit.
Yeah, I think there's not much to improve here as far as Vue's own types are concerned.
If you want to limit your function to certain event types, you will have to explicitly type them. The same is true for props, for example.
This is unrelated to #2474