valgfri parametere i TypeScript?


Ny på Typescript i en Angular-kontekst. Kan du merke egenskaper som valgfrie i eksempelet nedenfor? Hvordan vil du anbefale å spesifisere at et navigasjonselement ikke har barn? Med vanlig JS pleier jeg vanligvis å stole på en falsy-verdi for å sjekke om objektet har children-egenskapen. Men i Typescript, er det beste praksis å initialisere som en tom array? Hva med andre primitive egenskaper som kan ha eller ikke ha verdier?

import { Injectable } from '@angular/core';

export class NavItem {
  key: string;
  text: string;
  target: string;
  children: NavItem[];
}

const data: NavItem[] = [
  {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  },
  {
    key: "sales",
    target: "sales",
    text: "Sales"
  }
];

@Injectable()
export class NavService {
  getNav() {
    return data;
  }

}

Svar #1

Ja, det er veldig enkelt å markere en eiendom som valgfri, du legger til ? etter den:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}

Alternativt kan du også bruke en union med null eller undefined:

class NavItem {
  key: string;
  text: string;
  target: string;
  children: NavItem[] | undefined;
}

Med det sagt, har du misforstått noe veldig viktig, dette er feil:

const data: NavItem[] = [
  {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  },
  {
    key: "sales",
    target: "sales",
    text: "Sales"
  }
];

data er ikke et array av NavItem-elementer, for å få det må du opprette instanser av NavItem ved å bruke new-nøkkelordet, for eksempel:

const data: NavItem[] = [
  Object.assign(new NavItem(), {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  }),
  Object.assign(new NavItem(), {
    key: "sales",
    target: "sales",
    text: "Sales"
  })
];

Komplilereren klager ikke på å gjøre det fordi Typescript er basert på strukturell subtyping og de to typene deler samme struktur.
Men det er lett å se hvorfor det er feil ved å legge til metoder til NavItem:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];

  getKey() {
    return this.key;
  }
}

Prøv nå dette med koden din:

console.log(data[0].getKey());

Og du vil ende opp med:

Ufanget TypeError: data[0].getKey er ikke en funksjon

Du bør til og med få en kompilasjonsfeil som sier at getKey mangler i array-elementene dine.

Hvis du kun har tenkt å bruke NavItem som dataobjekter, spiller det egentlig ingen rolle, men du bør bare bruke grensesnitt eller typealias i stedet, siden de ikke kompilieres til JS og du unngår unødvendig minnebruk:

interface NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}

Rediger

Etter en kommentar fra @Zze har jeg bestemt meg for å legge til en enkel konstruktør som bruker "kraften" til Object.assign:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];

  constructor(data?: NavItem) {
      if (data) {
          Object.assign(this, data);
      }
  }
}

så :

new NavItem({
    key: "sales",
    target: "sales",
    text: "Sales"
})

Relaterte artikler