javascript - Tipuri de returnare condiționale în typescript


Încerc să parcurg un array de funcții (efectuând apeluri de rețea) care întorc diferite tipuri de obiecte de configurare. Pe baza acestei configurări, redau componente React cu diferite props. Dar am dificultăți să fac TypeScript să coopereze în această privință.

Iată un exemplu simplificat al a ceea ce aveam până acum;

type FirstConfig = {
  a: 'a';
};

type SecondConfig = {
  b: 'b';
};

type ConfigObject = FirstConfig | SecondConfig;
type ConfigFunction = () => ConfigObject;
const configArray: ConfigFunction[] = [() => ({ a: 'a' }), () => ({ b: 'b' })];

configArray.map(getConfig => {
  const { a, b } = getConfig();
  console.log(a, b);
});

Ori de câte ori parcurg array-ul de funcții de configurare și îl apelez, se pare că se plânge că niciuna dintre proprietățile definite pe ConfigObject nu este prezentă. Aveți vreun sfat/ghidare aici?

Răspuns #1

Acesta este un comportament așteptat. ConfigObject este fie FirstConfig, fie SecondConfig. Înainte de a accesa proprietățile lor distincte, trebuie să rezolvi tipul acestora sau să verifici dacă proprietatea există în acel tip.

Există diferite moduri în care poți realiza acest lucru.

  1. Definește un gardian de tip personalizat pentru verificarea unui tip.
const isFirstConfig = (config: ConfigObject): config is FirstConfig => !!(config as any).a;

link către cutia de nisip

  1. Verifică dacă proprietatea există în obiect
const config = getConfig();
if ("a" in config) {
  // the config is of FirstConfig type here
}
  1. Adaugă o proprietate comună pentru toate tipurile de configurare prin care poți verifica tipul acestora
type FirstConfig = {
  type: "first";
  a: "a";
};

type SecondConfig = {
  type: "second";
  b: "b";
};

atunci poți verifica tipurile astfel

const config = getConfig();
if (config.type === "first") {
  console.log("first type");
  // config is FirstConfig type in this 'if' block
}

nisipar

  1. Creează un tip pentru toate configurațiile cu proprietățile setate ca opționale
type ConfigObject = {
  a?: "a";
  b?: "b";
};

În acest caz, poți scrie codul tău inițial:

  const { a, b } = getConfig();

  console.log({ a, b });

nisipar