typescript - Vue: Typet props-grensesnitt med valgfrie egenskaper


Jeg laget en metode som jeg vil skal være tilgjengelig på alle mine Vue-instansene, som jeg kan kalle i tilfelle en feil og rendre en spesifikk feilekomponent. Noe som vue-error-page. Jeg bruker TypeScript, og nå vil jeg sørge for at komponenten kalles med riktig typede props, for å få en kompileringstid-feil hvis det er en skrivefeil i de overførte propsene.

For øyeblikket har jeg dette i en shims.d.ts-fil:

import Vue, {VueConstructor} from 'vue'

declare module 'vue/types/vue' {
    interface Vue {
        $error (component:VueConstructor<Vue>, props:unknown) : void;
    }
}

Som lar meg kalle pluginen min slik. Det overførte objektet samsvarer med props-definisjonen til ErrorPage-komponenten:

import Vue from "vue";
import ErrorPage from "./views/ErrorPage.vue";
export default Vue.extend({
  mounted() {
    this.$error(ErrorPage, { errorTitle: "Could not load the page" });
  }
});

Mens dette fungerer, vil jeg få en kompileringstid-feil hvis props ikke matcher det komponenten forventer.

Så jeg tenkte jeg skulle endre shims.d.ts på denne måten:

declare module 'vue/types/vue' {
    interface Vue {
        $error<Props> (component:ExtendedVue<Vue, unknown, unknown, unknown, Props>, props:Props) : void;
    }
}

Nå får jeg kompileringstidsfeil når props-objektet ikke samsvarer. Imidlertid får jeg også feil når jeg ikke sender inn valgfrie egenskaper. Min ErrorPage-komponent ser slik ut:

import Vue from "vue";
export default Vue.extend({
  name: "Error",
  props: {
    errorTitle: {
      type: String,
      required: true,
      default: "Error"
    },
    errorDescription: {
      type: String,
      required: false,
      default:
        "Something went wrong."
    }
  }
});

Hvis jeg ikke sender errorDescription, bør jeg ikke få en feil. Det er det jeg prøver å oppnå. Jeg vil kunne gjøre følgende ting:

// Should compile and does right now.
this.$error(ErrorPage, {errorTitle: "Oops", errorDescription: "Something went wrong" });

// Should compile and does not right now. Fails with error:
// Argument of type '{ errorTitle: string; }' is not assignable to parameter of type '{ errorTitle: string; errorDescription: string; }'.
// Property 'errorDescription' is missing in type '{ errorTitle: string; }' but required in type '{ errorTitle: string; errorDescription: string; }'."
this.$error(ErrorPage, {errorTitle: "Oops" });

TL;DR Spørsmål:

Hvordan kan jeg gjøre metodekallet mitt typesikkert med props som argument, samtidig som jeg kan utelate valgfrie egenskaper? Jeg kan endre både shims.d.ts og ErrorPage-komponenten.

Svar #1

Selv om du markerer det som ikke nødvendig, er TypeScript-typen fortsatt String, og som sådan må du sende det når du kaller metoden.

Du kan prøve dette (jeg har ikke testet om det fungerer)

Deklarer en type som kan være null, ved å bruke et alias

type ErrorDescriptionType = String | undefined | null

Og deretter bruk dette som typen for errorDescription

errorDescription: {
  type: Object as () => ErrorDescriptionType,
}