当使用打字稿定义发射时,使用发射事件名称的动态值

问题描述 投票:0回答:1

我是一名经验丰富的 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,并使用各自的类型对它们进行类型转换。

我尝试过内联类型断言。

无论我做什么,我都会在事件名称下看到红色下划线。

非常感谢任何帮助。

typescript vue.js vuejs3
1个回答
0
投票

我想通了。对于遇到此问题的其他人,解决方案是使用其他 vue 语法来定义发出。

这是我的解决方案:

const emit = defineEmits<{
    (e: RequestAction, value: any): void
    (e: RequestActionError, value: AxiosError<RequestErrorResponse<any>>): void
    (e: 'canceled', value?: any): void
}>();

我希望这可以帮助任何遇到此问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.