En grænseflade er en form af et objekt. Et standard JavaScript-objekt er et kort af key:value-par. JavaScript-objektnøgler er i næsten alle tilfælde strenge, og deres værdier er alle understøttede JavaScript-værdier (primitive eller abstrakte).
En grænseflade fortæller TypeScript-compileren om egenskabsnavne, som et objekt kan have, og deres tilsvarende værdityper. Derfor er interface en type og er en abstrakt type, da den er sammensat af primitive typer.
Når vi definerer et objekt med egenskaber (nøgler) og værdier, opretter TypeScript en implicit grænseflade ved at se på egenskabsnavnene og datatypen for deres værdier i objektet. Dette sker på grund af typeinferencen.
I ovenstående eksempel har vi oprettet et objekt student med firstName, lastName, age og getSalary felter og tildelt nogle indledende værdier. Ved hjælp af disse oplysninger opretter TypeScript en implicit interfacetype for student.
En grænseflade er ligesom et objekt, men den indeholder kun oplysninger om objektets egenskaber og deres typer. Vi kan også oprette en interfacetype og give den et navn, så vi kan bruge den til at annotere objektværdier, men her har denne interface ikke et navn, da den blev oprettet implicit. Du kan sammenligne dette med funktionstypen i den foregående lektion, som først blev oprettet implicit, og derefter oprettede vi en funktionstype eksplicit ved hjælp af typealias.
Lad os prøve at rode med objektets egenskaber, efter at den er blevet defineret.
Som du kan se af ovenstående eksempel, husker TypeScript formen på et objekt, da typen ross er den implicitte grænseflade. Hvis vi forsøger at overskrive værdien af en egenskab med en værdi af en anden type end den, der er angivet i grænsefladen, eller forsøger at tilføje en ny egenskab, som ikke er angivet i grænsefladen, vil TypeScript-compileren ikke kompilere programmet.
Hvis du ønsker, at et objekt grundlæggende skal have en hvilken som helst egenskab, kan du eksplicit markere en værdi any, og TypeScript-compileren vil ikke udlede typen fra den tildelte objektværdi. Der er andre bedre måder at opnå præcis dette på, og vi vil gennemgå dem i denne artikel.
Den implicitte grænseflade, vi har set indtil nu, er teknisk set en type, men den blev ikke defineret eksplicit. Som diskuteret er en grænseflade ikke andet end den form, som et objekt kan tage. Hvis du har en funktion, der accepterer et argument, som skal være et objekt, men af en bestemt form, skal vi annotere dette argument (parameter) med en interfacetype.
I ovenstående eksempel har vi defineret en funktion getPersonInfo, som accepterer et objektargument, der har firstName, lastName, age og getSalary felter af specificerede datatyper. Bemærk, at vi har brugt et objekt, der indeholder egenskabsnavne og deres tilsvarende typer som en type ved hjælp af :<type>-annotationen. Dette er et eksempel på en anonym grænseflade, da grænsefladen ikke har et navn, den blev brugt inline.
Det hele virker lidt kompliceret at håndtere. Hvis ross objektet bliver mere kompliceret, og det skal bruges flere steder, virker TypeScript bare som en ting, som du kunne lide i starten, men som nu bare er en svær ting at håndtere. For at løse dette problem definerer vi en grænsefladetype ved hjælp af nøgleordet interface.
I eksemplet ovenfor har vi defineret en grænseflade Person, der beskriver formen på et objekt, men denne gang har vi et navn, som vi kan bruge til at henvise til denne type. Vi har brugt denne type til at annotere ross-variablen samt person-argumentet i getPersonIfo-funktionen. Dette vil informere TypeScript om at validere disse enheder i forhold til formen Person.
Hvorfor bruge en grænseflade?
Interfacetype kan være vigtig for at håndhæve en bestemt form. Typisk i JavaScript stoler vi ved kørselstid blindt på, at et objekt altid vil indeholde en bestemt egenskab, og at denne egenskab altid vil have en værdi af en bestemt type som {age: 21, ...} som eksempel.
Når vi rent faktisk begynder at udføre operationer på denne egenskab uden først at kontrollere, om denne egenskab findes på objektet, eller om dens værdi er den, vi forventede, kan det gå galt, og det kan gøre din applikation ubrugelig bagefter. F.eks. er {age: '21', ...}, her age værdien en string.
Interfaces giver en sikker mekanisme til at håndtere sådanne scenarier på kompileringstidspunktet. Hvis du ved et uheld bruger en egenskab på et objekt, der ikke findes, eller bruger værdien af en egenskab i den ulovlige operation, vil TypeScript-kompileren ikke kompilere dit program. Lad os se et eksempel.