javascript - Skicka in parametrar till funktion genom att sprida ett parametrar-objekt fungerar inte


Jag vill skicka in alla parametrar till den här funktionen genom att sprida ett params-objekt på det här sättet, som detta SO-svar:

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;
}

Mitt försök:

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

Komplileringstidens fel:

Förväntade 1-7 argument, men fick 0 eller fler.ts(2556) toast.service.ts(18, 9): Ett argument för 'content' gavs inte.

Varför får jag detta fel? Jag har följt SO-svaret.

Svar #1

Du får detta eftersom Object.values(toastArgs) tolkas som:

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

Typescript har egentligen inte begreppet av en arrays 'length'. Såvitt typescript är bekymrad, skulle toastArgs kunna vara { x: true }, och det skulle uppfylla typen av Object.values(toastArgs). Du kan testa detta så här:

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

Ett sätt att uppnå det du letar efter är att refaktorera din showToast-metod för att istället ta ett enda objekt, istället för positionsargument:

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
}

Du kan då kalla:

service.showToast(toastArgs)

Alternativt kan du också använda en typförklaring, utan att refaktorera din kod på följande sätt:

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

Svar #2

Object.values() stöds från es2017, ECMAScript_2017. Och standardmålversionen för TypeScript är ES3. Felet kan åtgärdas genom att helt enkelt lägga till kompilatoralternativet --target es2017.