我是一名经验丰富的 Vue 开发人员,但我对 Typescript 很陌生,我所说的“新”是指我 3 天前就开始使用它了。
我有一个 vue 组件,它将请求列表重新计算为名为“requestedTokens”的 prop,它是未来请求的对象,每个我需要从后端获取一些身份验证令牌。
我正在调用请求操作的此对象,这是使用“NestedRequestProp”类型的请求操作的示例:
{
store: {
url: 'http://some-url',
method: 'post',
fields: {}
{
}
这些是我的类型声明:
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>;
};
我还定义了一些发射:
type Emit = {
[key in RequestAction]: [value?: object];
} & {
[key in RequestActionError]: [value: AxiosError<RequestErrorResponse<any>>]
} & {
canceled: [value: any|undefined]
};
const emit = defineEmits<Emit>();
如您所见,事件名称是 RequestActons 和 RequestActions,并附加字符串“Error”(例如:“store”或“storeError”)。
这是使用后端响应调用的成功函数。
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,
};
};
我的问题是这部分:
if (response && key in Actions) emit(key, response);
else if (error && !!props[errorListener]) emit((`${key}Error` as RequestActionError), error);
我在 vscode 中遇到这两个错误:
没有重载与此调用匹配。 最后一次超载出现以下错误。 “字符串”类型的参数不可分配给““取消””类型的参数。ts-plugin(2769) runtime-core.d.ts(229, 21):最后一个重载在这里声明。 const 键:字符串和
没有重载与此调用匹配。 最后一次超载出现以下错误。 类型为 '"errorIndex" | 的参数“错误显示” | “错误创建” | “错误存储”| “错误编辑”| “错误更新”| “错误销毁” | “errorRestore”不可分配给“canceled”类型的参数。 类型“errorIndex”无法分配给类型“canceled”。ts-plugin(2769) runtime-core.d.ts(229, 21):最后一个重载在这里声明。 const 键:字符串
我尝试将密钥转换为 ActionRequest。
我尝试为 successEvent、errorEvent 定义单独的 const,并使用各自的类型对它们进行类型转换。
我尝试过内联类型断言。
无论我做什么,我都会在事件名称下看到红色下划线。
非常感谢任何帮助。
我想通了。对于遇到此问题的其他人,解决方案是使用其他 vue 语法来定义发出。
这是我的解决方案:
const emit = defineEmits<{
(e: RequestAction, value: any): void
(e: RequestActionError, value: AxiosError<RequestErrorResponse<any>>): void
(e: 'canceled', value?: any): void
}>();
我希望这可以帮助任何遇到此问题的人。