I’m an experienced Vue dev but I’m new to typescript and by new I mean I’ve started 3 days ago with it.
I have a vue component that recules a list of request as a prop called ‘requestedTokens’ that is an object of future requests for each i need to fetch some auth tokens from the backend.
I’m calling this object of requests actions and here is an example of a request action that is using the type ‘NestedRequestProp’:
{
store: {
url: 'http://some-url',
method: 'post',
fields: {}
{
}
These are my type declarations:
const Actions = ['index', 'show', 'create', 'store', 'edit', 'update', 'destroy', 'restore'] as const;
const ActionErrors = ['errorIndex', 'errorShow', 'errorCreate', 'errorStore', 'errorEdit', 'errorUpdate', 'errorDestroy', 'errorRestore'] as const;
const ActionListeners = ['onIndex', 'onShow', 'onCreate', 'onStore', 'onEdit', 'onUpdate', 'onDestroy', 'onRestore'] as const;
const ActionErrorListeners = ['onErrorIndex', 'onErrorShow', 'onErrorCreate', 'onErrorStore', 'onErrorEdit', 'onErrorUpdate', 'onErrorDestroy', 'onErrorRestore'] as const;
type RequestProp<FieldsType = object> = {
url: string
method: Method
fields?: FieldsType
};
type NestedRequestProp<FieldsType = object> = {
[key in RequestAction]: RequestProp<FieldsType>;
};
I also have some emits defined:
type Emit = {
[key in RequestAction]: [value?: object];
} & {
[key in RequestActionError]: [value: AxiosError<RequestErrorResponse<any>>]
} & {
canceled: [value: any|undefined]
};
const emit = defineEmits<Emit>();
As you can see the event name are the RequestActons and the RequestActions with the string “Error” appended (EX.: ‘store’ or ‘storeError’).
Here is the success function that is being called with the response from the backend.
const success = async ({ status, data, wrapper }: {
status: number;
data: {
token: Token;
};
wrapper: typeof FormWrapper;
}) => {
if (status !== 201) return;
for (const key of Object.keys(data.token)) {
const listener = `on${capitalize(key)}` as RequestActionListener;
const errorListener = `on${capitalize(key)}Error` as RequestActionListener;
if (!!props[listener]) {
processing.value = true;
const { url, method, fields = {}} = props.requestedTokens[key as RequestAction];
const [response, error] = await ApiCaller.requestWithError(url, method, fields, {
headers: {
[auth.authorizationKey]: data.token[key as RequestAction],
}
});
if (response && key in Actions) emit(key, response);
else if (error && !!props[errorListener]) emit((`${key}Error` as RequestActionError), error);
processing.value = false;
}
}
wrapper.cancel();
if (tokens.value) tokens.value = {
key: auth.authorizationKey,
token: data.token,
};
};
My problem is with this part of it:
if (response && key in Actions) emit(key, response);
else if (error && !!props[errorListener]) emit((`${key}Error` as RequestActionError), error);
I’m getting these two errors in vscode:
No overload matches this call.
The last overload gave the following error.
Argument of type ‘string’ is not assignable to parameter of type ‘”canceled”‘.ts-plugin(2769)
runtime-core.d.ts(229, 21): The last overload is declared here.
const key: string
And
No overload matches this call.
The last overload gave the following error.
Argument of type ‘”errorIndex” | “errorShow” | “errorCreate” | “errorStore” | “errorEdit” | “errorUpdate” | “errorDestroy” | “errorRestore”‘ is not assignable to parameter of type ‘”canceled”‘.
Type ‘”errorIndex”‘ is not assignable to type ‘”canceled”‘.ts-plugin(2769)
runtime-core.d.ts(229, 21): The last overload is declared here.
const key: string
I’ve tried to cast key as ActionRequest.
I’ve tried to define separate const for successEvent, errorEvent and type cast them with the respective types.
I’ve tried inline type assertion.
Whatever I do I’m getting red underlines under the event names.
Any help with be very appreciated.
8
I figured out. For anyone else having this problem the solution is to use the other vue syntax for defining emits.
Here is my solution:
const emit = defineEmits<{
(e: RequestAction, value: any): void
(e: RequestActionError, value: AxiosError<RequestErrorResponse<any>>): void
(e: 'canceled', value?: any): void
}>();
I hope this help anyone having this problem.