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"
})
