网站搜索

javascript - 通过对象展开一个参数对象传递参数给函数不起作用


我想通过像这个 SO 回答中那样展开一个 params 对象来传递所有参数给这个函数:

public showToast(
    content: string,
    buttonLabel = 'Ok',
    hideDelay?: number,
    buttonAction?: Function,
    uniqueKey?: string,
    canBeCleared?: boolean,
    templateCtrl?: Object
): Toast {
    const toast = new Toast(
        content,
        this,
        buttonLabel,
        hideDelay,
        buttonAction,
        uniqueKey,
        canBeCleared,
        templateCtrl
    );
    toast.id = !this.lastToast ? 1 : this.lastToast.id + 1;
    this.toasts.push(toast);
    toast.top = toast.fromTop;

    // hiding is handled in the ToastComponent
    return toast;
}

我的尝试:

const toastArgs = {
    content: 'test toast',
    buttonLabel: 'test button',
    hideDelay: 1000,
    buttonAction: () => 5,
    uniqueKey: 'uk',
    canBeCleared: true,
    templateCtrl: { strl: 3 }
};
service.showToast(...Object.values(toastArgs));

编译时错误:

预期 1-7 个参数,但得到了 0 个或更多。ts(2556) toast.service.ts(18, 9):没有提供 'content' 参数。

我为什么会得到这个错误?我已经按照 SO 的答案做了。

答案#1

你会收到这个信息,因为 Object.values(toastArgs) 被推断为:

(true | "test toast" | "test button" | 1000 | (() => number) | "uk" | {
    readonly strl: 3;
})[]

TypeScript 并不真正有数组“长度”的概念。在 TypeScript 看来,toastArgs 可能是 { x: true },它也会满足 Object.values(toastArgs) 的类型。你可以像下面这样测试:

const toastArgsValid = {
  content: 'test toast',
  buttonLabel: 'test button',
  hideDelay: 1000,
  buttonAction: () => 5,
  uniqueKey: 'uk',
  canBeCleared: true,
  templateCtrl: {strl: 3},
};

const toastArgsValuesValid = Object.values(toastArgsValid);

type ToastParamsValid = typeof toastArgsValuesValid;

const toastArgsInvalid = {
  x: true,
};

const toastArgsValuesInvalid: ToastParamsValid = Object.values(
  toastArgsInvalid,
); // No error here since the invalid type is a subtype of the valid type

实现你所寻找的一个方法是重构你的 showToast 方法,使其接收一个对象,而不是位置参数:

public showToast({
  content,
  buttonLabel,
  hideDelay,
  buttonAction,
  uniqueKey,
  canBeCleared,
  templateCtrl,
}: {
  content: string;
  buttonLabel: string;
  hideDelay?: number;
  buttonAction?: Function;
  uniqueKey?: string;
  canBeCleared?: boolean;
  templateCtrl?: Object;
}): Toast {
 // function body
}

你随后可以调用:

service.showToast(toastArgs)

或者你也可以使用类型断言,而无需像这样重构你的代码:

service.showToast(...(Object.values(toastArgs) as Parameters<typeof service.showToast>));

答案#2

Object.values() 从 es2017,即 ECMAScript_2017 开始被支持。而 TypeScript 的默认目标版本是 ES3。这个错误可以通过添加编译器选项 --target es2017 来修复。