JavaScript is de meest gebruikte programmeertaal voor webontwikkeling. Maar het mist ondersteuning voor type-controle, wat een essentiële functie is van moderne programmeertalen.

JavaScript is oorspronkelijk ontworpen als een eenvoudige scripttaal. De losse aard en afwezigheid van cruciale Objectgeoriënteerd Programmeren (OOP) functies vormen bepaalde uitdagingen voor ontwikkelaars:

  1. Beperkte documentatie en auto-aanvulling.

  2. Onvermogen om OOP-concepten te gebruiken.

  3. Gebrek aan typeveiligheid, wat leidt tot runtime-fouten.

  4. Uitdagingen bij refactoring en onderhoud.

  5. Afwezigheid van interfaces en integratiepunten.

TypeScript lost deze problemen op. Het is gebouwd om JavaScript een meer perfecte moderne programmeertaal te maken. Het helpt de ontwikkelaarservaring te verbeteren, biedt veel nuttige functies en verbetert de interoperabiliteit.

Dit artikel duikt in de basis van TypeScript. Ik zal je leren hoe je TS installeert en een project opzet. Vervolgens zullen we enkele belangrijke fundamenten behandelen. Je leert ook hoe TypeScript in JavaScript compileert, waardoor het compatibel is met browsers en Node.js-omgevingen.

Wat we zullen behandelen:

Vereisten

Voordat je in TypeScript duikt, is het belangrijk om een basisbegrip van bepaalde concepten te hebben om een soepelere leerreis te garanderen. Terwijl TypeScript JavaScript verbetert met statische types en andere krachtige functies, bouwt het voort op de kernprincipes van JavaScript. Dit is wat je moet weten:

1. JavaScript Basisprincipes

TypeScript is een superset van JavaScript, wat betekent dat het de mogelijkheden van JavaScript uitbreidt. Om TypeScript effectief te leren, moet je eerst een goed begrip hebben van de basisprincipes van JavaScript, waaronder:

  • Syntax en datatypes: Begrijp hoe je variabelen declareert (let, const, en var), werk met primitieve types (strings, getallen, booleans), en beheer arrays en objecten.

  • Controle stroom: Wees bekend met lussen (for, while), conditionele uitspraken (if-else, switch), en hoe zij de uitvoering van het programma aansturen.

  • Functions: Weet hoe functies te definiëren en aan te roepen, te werken met parameters, retourwaarden, en begrijp concepten zoals pijlfuncties en closures.

  • Objectgeoriënteerd programmeren (OOP): Leer over het creëren en werken met objecten, klassen en overerving. De op klassen gebaseerde functies van TypeScript bouwen sterk voort op het OOP-model van JavaScript.

  • Foutafhandeling: Begrijp hoe je try-catch-blokken kunt gebruiken om runtimefouten af te handelen.

2. Basis HTML en CSS

Hoewel TypeScript een taal is die voornamelijk met JavaScript wordt gebruikt, is het handig om een basisbegrip van HTML en CSS te hebben, vooral voor front-end ontwikkelaars. Dit komt doordat de meeste TypeScript-projecten het creëren of werken met webapplicaties omvatten

  • HTML: Begrijp hoe webpagina’s te structureren met behulp van tags, attributen en elementen.

  • CSS: Leer hoe je elementen kunt stylen met behulp van selectors, eigenschappen en waarden. Bekendheid met CSS-frameworks zoals Bootstrap is een bonus.

3. Bekendheid met Ontwikkelingstools

  • Een code-editor zoals Visual Studio Code, die uitstekende ondersteuning biedt voor TypeScript en extensies heeft.

  • Node.js en npm: Begrijp hoe je een ontwikkelomgeving opzet, JavaScript buiten de browser uitvoert en npm (Node Package Manager) gebruikt om afhankelijkheden te installeren.

  • Versiebeheer (Git): Leer de basisprincipes van Git om wijzigingen bij te houden en effectief samen te werken aan TypeScript-projecten.

Aan de slag – Hoe TypeScript te installeren

Om aan de slag te gaan met TypeScript moet je het installeren. Het is geen ingewikkeld proces. Met TypeScript geïnstalleerd, kun je zijn kracht benutten om hoogwaardige oplossingen te creëren.

Je kunt TS op twee manieren installeren:

  1. Globale Installatie: stelt je in staat om de compiler vanuit elke map op je computer te benaderen. Om TypeScript globaal te installeren, voer je het volgende commando uit:
npm install -g typescript

Dit commando maakt gebruik van de Node.js package manager, npm. Het installeert TypeScript globaal, waardoor het commando beschikbaar is in de commandoregel.

  1. Lokale Installatie: in dit geval wordt TypeScript alleen geïnstalleerd binnen een specifiek project. Deze methode zorgt voor versiecompatibiliteit en consistentie tussen teamleden. Om TypeScript lokaal te installeren, voer je het volgende commando uit:
npm install typescript --save-dev

In tegenstelling tot de globale installatie, installeert dit commando TypeScript als een ontwikkelingsafhankelijkheid. Het tsc commando is alleen beschikbaar voor project-specifiek gebruik, dat wil zeggen het specifieke project waar je het commando uitvoert.

Kun je nu naadloos TypeScript installeren? Ik hoop het!

Hoe je TypeScript-projecten organiseert

Het organiseren van een TypeScript-project houdt in dat je de bestanden structureert met betekenisvolle namen en mappen, concerns scheidt en modules gebruikt voor encapsulatie en herbruikbaarheid.

De .ts extensie geeft TypeScript-bestanden aan en bevat code die wordt omgezet in JavaScript voor uitvoering.

TypeScript ondersteunt ook .d.ts bestanden, ook wel bekend als type definitie bestanden. Deze bestanden bieden type-informatie over externe JavaScript bibliotheken of modules, wat helpt bij betere type-controle en code-aanvulling, evenals het verbeteren van de ontwikkelings efficiëntie. Hieronder volgt een voorbeeld van een goede TS projectstructuur:

my-ts-project/
├── src/ 
│   ├── components/ 
│   │   ├── Button.tsx
│   │   ├── Input.tsx
│   │   └── Modal.tsx
│   ├── services/ 
│   │   ├── api.ts
│   │   └── authService.ts
│   ├── utils/ 
│   │   ├── helpers.ts 
│   │   └── validators.ts
│   ├── models/ 
│   │   ├── User.ts
│   │   └── Product.ts
│   ├── index.tsx 
│   └── styles/ 
│       ├── global.css
│       └── theme.css
├── public/ 
│   ├── index.html
│   └── assets/ 
│       ├── images/
│       └── fonts/
├── tsconfig.json
└── package.json

Laten we begrijpen wat hier aan de hand is:

  1. src/: Deze map bevat alle broncode voor het project.

    • components/: Bevat herbruikbare UI-componenten (bijvoorbeeld, Button, Input, Modal). Het gebruik van .tsx (TypeScript JSX) stelt je in staat om JSX met typeveiligheid te schrijven.

    • services/: Bevat services die interageren met externe API’s of applicatielogica afhandelen (bijvoorbeeld, api.ts voor API-aanroepen, authService.ts voor authenticatie).

    • utils/: Bevat hulpfuncties en utility klassen voor veelvoorkomende taken (bijvoorbeeld, helpers.ts voor datumformattering, validators.ts voor invoervalidatie).

    • models/: Definieert TypeScript interfaces of klassen om gegevensstructuren weer te geven (bijvoorbeeld, User.ts, Product.ts).

    • index.tsx: Het belangrijkste toegangspunt van de applicatie.

    • styles/: Bevat CSS of andere opmaakbestanden.

  2. public/: Deze map bevat statische bronnen die niet verwerkt worden door TypeScript (bijvoorbeeld HTML, afbeeldingen, lettertypen).

  3. tsconfig.json: Het TypeScript-configuratiebestand waarin compileropties worden gespecificeerd.

  4. package.json: Het manifestbestand van het project waarin afhankelijkheden, scripts en andere projectmetadata worden vermeld.

Een korte opmerking over de naamgevingsconventies zodat u ze hier begrijpt:

  • Gebruik PascalCase voor klassenamen (bijvoorbeeld User, Product).

  • Gebruik camelCase voor functienamen en variabelen (bijvoorbeeld getUser, firstName).

  • Gebruik betekenisvolle en beschrijvende namen voor bestanden en mappen.

Deze structuur bevordert modulariteit, herbruikbaarheid en een betere organisatie, waardoor uw TypeScript-projecten gemakkelijker te onderhouden en schalen zijn.

Door uw TS-projecten op de juiste manier te organiseren, verbetert u de code-onderhoudbaarheid, leesbaarheid en samenwerking in TypeScript-ontwikkelingsworkflows.

Hoe typen werkt in TypeScript

Net als bij elke andere getypeerde programmeertaal vertrouwt TypeScript op type-definities, meestal genoemd Typing.

Typing is een term die wordt gebruikt in programmeren om datatypen te definiëren voor variabelen, methodenparameters en retourwaarden binnen de code.

Typing stelt u in staat om snel en vroegtijdig fouten op te sporen tijdens de ontwikkeling, een superkracht die helpt om de codekwaliteit te verbeteren.

Om een type in TypeScript te specificeren, plaatst u een dubbelepunt (:) en het gewenste datatypenaam na uw variabelennaam. Hier is een voorbeeld:

let age: number = 2;

De bovenstaande variabele is gedeclareerd met het type number. In TypeScript betekent dit dat het alleen getallen kan opslaan en niets anders.

Typing Technieken

In TypeScript kan data op twee hoofdmanieren worden getype:

  1. Statistisch Typen: Statisch typen verwijst naar het expliciet specificeren van het datatypen van variabelen en andere entiteiten in de code tijdens de ontwikkeling. De TypeScript-compiler dwingt deze typedefinities af, wat helpt om typegerelateerde fouten vroegtijdig op te sporen. Bijvoorbeeld:
let age: number = 25;

Hier wordt de variabele leeftijd expliciet verklaard om het type nummer te hebben. Dit zorgt ervoor dat alleen numerieke waarden eraan kunnen worden toegewezen, waardoor het risico op runtime-fouten wordt verkleind.

  1. Dynamische Typing: Dynamische typing in TypeScript verwijst naar situaties waarin het type van een variabele tijdens runtime wordt bepaald. Dit kan voorkomen wanneer variabelen het type any krijgen toegewezen, waardoor ze waarden van elk type kunnen bevatten. TypeScript voert geen typecontrole uit op bewerkingen met variabelen van het type any.
let value: any;
value = 25; // Nummer
value = "Hello"; // Tekenreeks

Hoewel TypeScript primair een statisch getypeerde taal is, kan dynamische typing nog steeds nuttig zijn in specifieke gevallen, zoals:

  • Werken met externe bibliotheken die type-definities missen.

  • Communiceren met dynamisch gestructureerde gegevens (bijvoorbeeld JSON-responsen van API’s met onbekende structuren).

  • Snelle prototyping of wanneer type-informatie niet beschikbaar is tijdens de initiële ontwikkelingsfase.

Statisch vs. Dynamische Typing in TypeScript

Statische typering is aanzienlijk gebruikelijker in TypeScript, aangezien het een van de kernfuncties is die TypeScript onderscheidt van JavaScript. Door strikte typecontroles af te dwingen, verbetert statische typering de code-onderhoudbaarheid, vermindert het bugs en verbetert het de productiviteit van ontwikkelaars.

Dynamische typering wordt meestal gebruikt voor gevallen waarin flexibiliteit vereist is of bij het omgaan met gegevens waarvan de structuur niet op voorhand kan worden bepaald. Bedenk echter dat zwaar vertrouwen op dynamische typering (bijvoorbeeld overmatig gebruik van het any type) over het algemeen wordt afgeraden, aangezien dit de voordelen van het statische typeringssysteem van TypeScript ondermijnt.

Dus hoewel dynamische typering zijn plaats heeft in bepaalde randgevallen, is statische typering de voorkeurs- en meer gebruikelijk toegepaste benadering in TypeScript-ontwikkeling.

Type Inferentie en Unie Types

Type Inferentie

Type inferentie is een krachtige functie van TypeScript waarmee de compiler automatisch het type van een variabele kan afleiden op basis van de waarde die eraan is toegewezen tijdens de initialisatie. In eenvoudiger bewoordingen, TypeScript kijkt naar de waarde die je aan een variabele toewijst en beslist welk type het moet zijn, zelfs als je het type niet expliciet declareert.

Bijvoorbeeld:

typescriptCopyEditlet age = 25; // TypeScript leidt af dat 'leeftijd' van het type 'number' is
age = "hello"; // Fout: Type 'string' is niet toewijsbaar aan type 'number'

In dit voorbeeld wordt de variabele leeftijd automatisch afgeleid als een nummer vanwege de initiële waarde, 25. Elke poging om leeftijd opnieuw toe te wijzen aan een waarde van een ander type (zoals een string) zal resulteren in een typefout.

Type-inferentie is bijzonder handig omdat het de noodzaak voor expliciete type-annotaties vermindert, waardoor je code schoner en leesbaarder wordt. Het biedt echter nog steeds de veiligheid en betrouwbaarheid van TypeScript’s type-checking.

Wanneer type-inferentie te gebruiken:
  • Eenvoudige toewijzingen: Gebruik type-inferentie voor eenvoudige toewijzingen waarbij het type duidelijk is uit de waarde.

  • Standaardwaarden: Bij het verstrekken van standaardwaarden voor variabelen of functieparameters zorgt type-inferentie ervoor dat het juiste type wordt toegepast zonder handmatige annotaties.

  • Snelle prototyping: Tijdens de vroege ontwikkelingsfasen kan type-inferentie boilerplatecode verminderen terwijl nog steeds typeveiligheid wordt afgedwongen.

Unie Types

Unie types stellen een variabele in staat om waarden van meerdere types vast te houden. Ze worden gedefinieerd door een verticale streep (|) tussen de types te plaatsen. Deze functie is bijzonder handig wanneer een variabele tijdens zijn levenscyclus legitiem meer dan één type kan hebben.

Bijvoorbeeld:

typescriptCopyEditlet numOrString: number | string; // 'numOfString' kan zowel een nummer als een string vasthouden
numOrString = 25; // Geldig
numOrString = "hello"; // Geldig
numOrString = true; // Fout: Type 'boolean' is niet toewijsbaar aan type 'number | string'

Je kunt zelfs unie types definiëren met meer dan twee mogelijke types:

typescriptCopyEditlet multiType: number | string | boolean;
multiType = 42; // Geldig
multiType = "TypeScript"; // Geldig
multiType = false; // Geldig
Wanneer unie types te gebruiken:
  • Flexibele functieparameters: Wanneer een functie meerdere typen invoer kan accepteren.

      typescriptCopyEditfunction printValue(value: string | number) {
        console.log(value);
      }
    
  • Omgaan met diverse datastructuren: Wanneer je werkt met API’s of externe gegevensbronnen waar velden in type kunnen variëren.

  • Optionele of multi-staat variabelen: Bijvoorbeeld, een variabele die een laadtoestand kan weergeven als een boolean, een fout als een string, of geldige gegevens als een object:

      typescriptCopyEditlet status: boolean | string | { success: boolean; data: any };
    

Hoe om te gaan met objecten, arrays en functietypen in TypeScript

Om TypeScript meester te worden, moet je de verschillende gegevenstypen begrijpen die in TypeScript worden ondersteund en hoe en wanneer je ze moet gebruiken.

De JavaScript primitieve types zoals strings, getallen, booleans, en meer definiëren ook de fundamentele bouwstenen van gegevens in TypeScript. Maar in het bijzonder zijn Objecten, Arrays, en Functies essentieel voor het bouwen van robuuste applicaties. Met objecten, arrays en functies kun je gegevens beter beheren en ze efficiënt gebruiken in de ontwikkeling.

Object Types in TypeScript

Objecttypes vertegenwoordigen het blauwdruk voor het maken van objecten in TypeScript. Je kunt objecten gebruiken om hun vorm te definiëren, vergelijkbaar met hoe klassen worden gebruikt in objectgeoriënteerd programmeren (OOP). Maar objecten missen de gedragsaspecten en encapsulatie die klassen bieden.

Om een objecttype te definiëren, definieer je expliciet de blauwdruk van het object na de dubbelepunt (:). Bijvoorbeeld:

// Object Type Initialisatie

let student: {
    name: string;
    age: number;
    matricNumber: string | number;
 };

// Het toewijzen van het Object met actuele gegevens

student = {
    name: "Akande"
    age: 21,
    matricNumber: 21/52 + "HP" + 19,
};

Merk op dat de eigenschappen eindigen met een puntkomma ; in plaats van een komma ,, die ze in een daadwerkelijk object beëindigt.

Het bovenstaande is de primaire manier om een object in TypeScript te definiëren. Een andere manier is om interfaces te gebruiken, die ik later in dit artikel zal behandelen.

Array Types in TypeScript

Arrays in TypeScript stellen je in staat om meerdere waarden van hetzelfde of verschillende datatypes in een enkele variabele op te slaan. Ze verbeteren de veiligheid en duidelijkheid van je code door typeconsistentie over de array-elementen af te dwingen.

In TypeScript kunnen arraytypes op twee manieren worden gedefinieerd:

1. Gebruikmakend van het Array<type> model

Deze syntaxis gebruikt het generieke Array type, waarbij type het type elementen vertegenwoordigt dat de array kan bevatten.

typescriptCopyEditlet numbers: Array<number> = [1, 2, 3, 4, 5];
let mixedArray: Array<number | string> = [1, 2, 3, 4, 5, "Hello"];
  • numbers Voorbeeld: Deze array kan alleen nummers bevatten. Proberen een string of een ander type aan deze array toe te voegen zal resulteren in een typefout.

      typescriptCopyEditnumbers.push(6); // Geldig
      numbers.push("Hallo"); // Fout: Type 'string' is niet toewijsbaar aan type 'number'
    
  • mixedArray Voorbeeld: Deze array maakt gebruik van een unie type (number | string), waardoor het zowel getallen als strings kan opslaan.

      typescriptCopyEditmixedArray.push(42); // Geldig
      mixedArray.push("TypeScript"); // Geldig
      mixedArray.push(true); // Fout: Type 'boolean' is niet toewijsbaar aan type 'number | string'
    

2. Gebruik makend van het type[] model

Deze syntaxis voegt vierkante haken ([]) toe aan het type elementen dat het array kan bevatten.

typescriptCopyEditconst numbers: number[] = [1, 2, 3, 4, 5];
const mixedArray: (string | number)[] = [1, 2, 3, 4, 5, "Hello"];
  • nummers Voorbeeld: Net als het Array<number> voorbeeld, kan dit array alleen nummers bevatten.

      typescriptCopyEditnumbers[0] = 10; // Geldig
      numbers.push("Hi"); // Fout: Type 'string' is niet toewijsbaar aan type 'number'
    
  • mixedArray Voorbeeld: Net als de eerdere mixedArray, staat deze array zowel getallen als strings toe, waardoor flexibiliteit wordt geboden waar het type data kan variëren.

    typescriptCopyEditmixedArray[1] = "World"; // Geldig
      mixedArray.push(true); // Fout: Type 'boolean' is niet toewijsbaar aan type 'string | number'
    

Hoe Arrays te Gebruiken in TypeScript

Arrays zijn veelzijdig en worden vaak gebruikt voor het opslaan van collecties van gerelateerde data. Hier zijn een paar praktische scenario’s:

Homogene Data Opslaan:
Wanneer alle elementen in de array hetzelfde type delen, zoals een lijst van gebruikers-ID’s of productprijzen:

typescriptCopyEditconst userIds: number[] = [101, 102, 103];
const productPrices: Array<number> = [29.99, 49.99, 19.99];

Opslaan van Heterogene Data:
Wanneer elementen verschillende typen kunnen hebben, zoals een lijst met berichten die tekst en optionele metadata bevatten:

typescriptCopyEditconst messages: (string | object)[] = [
  "Welcome",
  { type: "error", text: "Something went wrong" },
];

Itereren Over Arrays:
Arrays in TypeScript kunnen worden gebruikt in lussen met volledige typeveiligheid:

typescriptCopyEditconst scores: number[] = [80, 90, 70];
scores.forEach((score) => console.log(score + 5)); // Voegt 5 toe aan elk punt

Functieparameters en Retourtypes:
Arrays kunnen ook worden doorgegeven als functieparameters of worden geretourneerd door functies met strenge typen:

typescriptCopyEditfunction getNumbers(): number[] {
  return [1, 2, 3];
}
function printStrings(strings: string[]): void {
  strings.forEach((str) => console.log(str));
}

Functietypes in TypeScript

Functietypes in TypeScript beschrijven de vorm van functies, inclusief parameter typen en retourtypen. Functietypes worden gedefinieerd door de parameter typen expliciet te specificeren tijdens de declaratie. Het retourtype wordt gespecificeerd door : toe te voegen en het type om onmiddellijk na de haakjes terug te geven. Bijvoorbeeld:

function addition (a: number, b: number): number {
return a + b;
}

De bovenstaande functie neemt twee getallen aan, telt ze op en retourneert een getal. De functie werkt niet als een van de argumenten geen getallen zijn en als het iets anders retourneert dan een getal. Bijvoorbeeld:

  1. Het aanroepen van de functie met een string als argument:
// Dit zal niet werken omdat het getallen verwacht, en een van de argumenten een string is

addition(1, "two");
  1. Het herschrijven van de functie om een string terug te geven:
// De functie zal een fout retourneren omdat het een string retourneert

function addition (a: number, b: number): string {
    let result = a + b;
    let returnStatement = `Addition of ${a} and ${b} is: ${result}`;
    return returnStatement;
}

Test de code zelf om te zien hoe deze voorbeelden werken.

Het begrijpen en effectief omgaan met objecten, arrays en functies in TypeScript stelt je in staat om type-veilige en onderhoudbare code te schrijven, waardoor de betrouwbaarheid en schaalbaarheid van je applicaties worden verbeterd.

Hoe maak je aangepaste types in TypeScript

Vaak volgt je ontwerppatroon niet de ingebouwde datatypen in TypeScript. Bijvoorbeeld, je kunt patronen hebben die dynamische programmering gebruiken. En dit kan problemen veroorzaken in je codebase. TypeScript biedt een oplossing voor het maken van aangepaste types om dit probleem aan te pakken.

Aangepaste types stellen je in staat om je gegevensstructuur en vormen te definiëren volgens jouw behoeften. Dit verbetert de leesbaarheid en onderhoudbaarheid van de code.

Het type sleutelwoord

Het type sleutelwoord stelt je in staat om type-aliassen te maken, en biedt een manier om aangepaste types te creëren. De types die je maakt kunnen opnieuw worden gebruikt in je codebase. Type-aliassen helpen bij het definiëren van unie-types of het combineren van types tot enkele aliassen. De syntaxis voor het maken van een aangepast type is als volgt:

// Syntax

type TypeAlias = type;

En hier is een voorbeeld:

De code hierboven maakt een aangepast type UserName, een unie van getallen en strings. Het gebruikt het gemaakte type om twee variabelen te definiëren om te controleren of het type werkt.

Merk op dat het aanbevolen is om een type-alias te laten beginnen met een hoofdletter.

Het type sleutelwoord wordt over het algemeen gebruikt voor primitieven – maar hoe zit het met het maken van een aangepast objecttype?

Hier komen Interfaces in beeld.

TypeScript Interfaces

Interfaces in TypeScript worden gebruikt om de structuur van objecten te definiëren. Ze dienen als blauwdrukken, waarbij ze de eigenschappen specificeren die een object moet hebben en hun respectievelijke types. Dit zorgt ervoor dat objecten voldoen aan een consistente vorm, wat zorgt voor typeveiligheid en duidelijkere code.

Het definiëren van een interface

Een interface wordt gedefinieerd met het sleutelwoord interface. De syntaxis ziet er als volgt uit:

typescriptCopyEditinterface InterfaceName {
  property1: Type;
  property2: Type;
}

Voorbeeld:

typescriptCopyEditinterface User {
  id: number;
  name: string;
  email: string;
}

const user: User = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
};

Dit is wat er gebeurt in dit voorbeeld:

  1. Interface declaratie (interface User):

    • Hier definiëren we een blauwdruk voor een User-object. Het geeft aan dat elk object van het type User de volgende eigenschappen moet hebben:

      • id van het type number

      • name van het type string

      • email van het type string

  2. Gebruikmakend van de interface (const user: User):

    • We verklaren een object user van het type User.

    • Het object moet alle eigenschappen hebben die zijn gedefinieerd in de interface User, met waarden van de gespecificeerde types. Als een eigenschap ontbreekt of als het type niet overeenkomt, zal TypeScript een fout veroorzaken tijdens de compilatie.

Bijvoorbeeld:

    typescriptCopyEditconst invalidUser: User = {
      id: 1,
      name: "Alice",
      // Fout: Eigenschap 'email' ontbreekt in het type
    };

Dus je vraagt je misschien af – waarom zou je interfaces moeten gebruiken?

  • Typeveiligheid: Zorgt ervoor dat objecten voldoen aan de verwachte structuur, waardoor runtime-fouten worden voorkomen.

  • Herbruikbaarheid: Dezelfde interface kan worden hergebruikt in verschillende delen van de toepassing, waardoor duplicatie wordt verminderd.

  • Codehelderheid: Maakt de code gemakkelijker te lezen en te begrijpen door de vorm van objecten expliciet te beschrijven.

Geavanceerde functies van interfaces

  1. Optionele eigenschappen: Je kunt eigenschappen optioneel maken door een vraagteken toe te voegen (?).

    typescriptCopyEditinterface Product {
       id: number;
       name: string;
       description?: string; // Optionele eigenschap
     }
    
     const product: Product = {
       id: 101,
       name: "Laptop",
     }; // Geldig, omdat 'description' optioneel is
    
  2. Alleen-lezen eigenschappen: Gebruik readonly om te voorkomen dat eigenschappen worden gewijzigd na initialisatie.

     typescriptCopyEditinterface Punt {
       readonly x: number;
       readonly y: number;
     }
    
     const punt: Punt = { x: 10, y: 20 };
     punt.x = 15; // Fout: Kan niet toewijzen aan 'x' omdat het een alleen-lezen eigenschap is
    
  3. Het uitbreiden van interfaces: Interfaces kunnen eigenschappen erven van andere interfaces, waardoor compositie mogelijk is.

     typescriptCopyBewerkeninterface Persoon {
       naam: string;
       leeftijd: number;
     }
    
     interface Werknemer extends Persoon {
       werknemerId: number;
     }
    
     const werknemer: Werknemer = {
       naam: "John",
       leeftijd: 30,
       werknemerId: 1234,
     };
    

Wanneer interfaces te gebruiken

Er zijn verschillende scenario’s waarin het een goed idee is om interfaces te gebruiken. Je kunt ze gebruiken wanneer je de structuur van objecten wilt definiëren en afdwingen die in je code worden doorgegeven.

Ze zijn ook nuttig in API-responsen, omdat ze je helpen om objecten die van API’s zijn ontvangen type te controleren. Dit zorgt ervoor dat de data aan je verwachtingen voldoet.

Interfaces zijn ook handig bij het werken met herbruikbare types. Wanneer meerdere delen van je applicatie objecten met dezelfde structuur gebruiken, voorkomen interfaces duplicatie.

Door gebruik te maken van interfaces kun je robuuste, onderhoudbare en type-veilige applicaties creëren. Ze zijn een essentieel kenmerk van TypeScript dat schoon en voorspelbaar codeert bevordert.

Generics en Literale Types

Generics in TypeScript stellen je in staat om herbruikbare componenten te maken die met verschillende datatypes kunnen werken. Ze laten je functies, klassen en interfaces schrijven zonder het exacte type van tevoren op te geven, waardoor je code flexibeler en onderhoudbaarder wordt.

Hier is een voorbeeld van een generieke functie en een generieke interface in TypeScript:

// Generieke interface voor een doos die elke waarde kan bevatten 

interface  Box<T> { 
    value: T; 
}

// Voorbeeld van gebruik

let  numberBox: Box<number> = { value: 10 };
let  stringBox: Box<string> = { value: "TypeScript" };

console.log(numberBox.value); // Uitvoer: 10  
console.log(stringBox.value); // Uitvoer: TypeScript

Je kunt generics gebruiken wanneer je niet zeker bent van je datatype.

In tegenstelling tot Generics, Letterlijke types stellen je in staat om exacte waarden op te geven die een variabele kan bevatten. Dit voegt meer specificiteit en typeveiligheid toe aan je code, waardoor ongewenste waarden niet kunnen worden toegewezen. Hier is een voorbeeld:

type Direction = 'up' | 'down' | 'left' | 'right';

Een variabele die met het bovenstaande type is gemaakt, kan alleen worden toegewezen aan de strings omhoog, omlaag, links en rechts.

Over het algemeen stelt het gebruik van aangepaste types in TypeScript je in staat om expressieve, herbruikbare en typeveilige datastructuren te creëren, waardoor je robuustere en onderhoudbare applicaties kunt ontwikkelen.

Hoe je types kunt samenvoegen in TypeScript

Het samenvoegen van types in TypeScript combineert meerdere typeverklaringen tot één enkele, verenigde type. Deze mogelijkheid stelt ontwikkelaars in staat om complexe types te bouwen uit kleinere, herbruikbare stukjes, wat de duidelijkheid, herbruikbaarheid en onderhoudbaarheid van de code verbetert.

1. Declaratie-samenvoeging in Interfaces

TypeScript ondersteunt declaratie-samenvoeging, waarbij meerdere interface-declaraties met dezelfde naam automatisch worden samengevoegd tot één interface. Dit laat je een bestaande interface uitbreiden door aanvullende eigenschappen of methoden te definiëren.

Voorbeeld:
typescriptCopyEditinterface User {
  id: number;
  name: string;
}

interface User {
  email: string;
}

const user: User = {
  id: 1,
  name: "Alice",
  email: "[email protected]",
};
Hoe het werkt:
  • De Gebruiker interface is twee keer gedeclareerd, elk met verschillende eigenschappen.

  • TypeScript voegt deze declaraties automatisch samen tot een enkele interface:

      typescriptCopyEditinterface Gebruiker {
        id: number;
        naam: string;
        e-mail: string;
      }
    
  • Als je het gebruiker-object maakt, moeten alle eigenschappen van de samengevoegde interface aanwezig zijn. Als een eigenschap ontbreekt, zal TypeScript een foutmelding geven.

Declaratie samenvoegen is bijzonder handig bij het werken met externe bibliotheken. Je kunt een bestaande interface uitbreiden of nieuwe eigenschappen toevoegen zonder de broncode van de bibliotheek te wijzigen.

2. Interface samenvoegen met behulp van het extends-trefwoord

Het extends-trefwoord maakt het mogelijk dat een interface eigenschappen en methoden erft van een andere, waardoor een nieuwe interface ontstaat die de eigenschappen van beide combineert.

Voorbeeld:
typescriptCopyEditinterface Person {
  name: string;
  age: number;
}

interface Employee extends Person {
  employeeId: number;
}

const employee: Employee = {
  name: "John",
  age: 30,
  employeeId: 101,
};
Hoe het werkt:
  • De Person interface definieert twee eigenschappen: name en age.

  • De Employee interface gebruikt het extends sleutelwoord om de eigenschappen van Person over te nemen.

  • De Employee interface voegt ook een nieuwe eigenschap toe, employeeId.

  • Het employee object moet alle eigenschappen van zowel Person als Employee bevatten.

Deze benadering is ideaal voor hiërarchische relaties. U kunt bijvoorbeeld een basisinterface definiëren voor gedeelde eigenschappen en deze uitbreiden voor gespecialiseerde types.

3. Type samenvoegen met de & operator

De & operator, bekend als het intersectietype, stelt u in staat om meerdere types te combineren tot een enkel type. Het resulterende type omvat alle eigenschappen en methoden van elk type.

Voorbeeld:
typescriptCopyEdittype Address = {
  city: string;
  country: string;
};

type ContactInfo = {
  email: string;
  phone: string;
};

type EmployeeDetails = Address & ContactInfo;

const employee: EmployeeDetails = {
  city: "New York",
  country: "USA",
  email: "[email protected]",
  phone: "123-456-7890",
};
Hoe het werkt:
  • Address en ContactInfo zijn twee afzonderlijke types.

  • MedewerkerDetails is een intersectietype gemaakt met behulp van Adres & Contactgegevens.

  • Het medewerker-object moet alle eigenschappen van zowel Adres als Contactgegevens bevatten. Ontbrekende of onjuist getypeerde eigenschappen zullen resulteren in een TypeScript-fout.

Intersectietypen zijn handig wanneer u ongerelateerde typen wilt combineren of samengestelde typen wilt maken voor specifieke gebruikssituaties, zoals API-responses die verschillende gegevensstructuren samenvoegen.

Wanneer elk van deze benaderingen te gebruiken

  1. Declaratie samenvoegen: Gebruik wanneer u een bestaande interface wilt uitbreiden of aanvullen, met name in externe bibliotheken of gedeelde codebases.

  2. extends trefwoord: Gebruik voor hiërarchische relaties waar een basisinterface kan worden gespecialiseerd in meer specifieke typen.

  3. Intersectietypen (&): Gebruik wanneer je meerdere niet-verwante typen moet combineren tot een enkel type voor specifieke gebruikssituaties.

Door deze samenvoegtechnieken en hun implicaties te begrijpen, kun je je TypeScript-code effectief structureren, wat de herbruikbaarheid en onderhoudbaarheid verbetert terwijl de typeveiligheid behouden blijft.

Bundeling en transformaties in TypeScript

Niet elke browser ondersteunt de nieuwste JavaScript die door TypeScript wordt gebruikt. Je kunt de TypeScript-compiler, of tsc, gebruiken om TypeScript-code (.ts-bestanden) om te zetten naar conventionele JavaScript (.js-bestanden) die universeel compatibel is met alle browsers. tsc vertaalt TypeScript-specifieke elementen zoals typen en klassen naar JavaScript-code die browsers kunnen interpreteren.

Om TypeScript-bestanden uit te voeren, is tsc je beste keuze. Je kunt tsc installeren met npm en vervolgens je .ts-bestanden omzetten naar .js-bestanden. Om tsc te gebruiken, geef je gewoon de naam van het TypeScript-bestand op vóór het tsc-commando. Als je bijvoorbeeld een bestand hebt met de naam app.ts, kun je het uitvoeren door te typen:

tsc app.ts

Webpack of Parcel worden vaak gebruikt om TypeScript-code op browsers te implementeren. Deze tools bundelen alle JavaScript-bestanden, inclusief die van TypeScript, voor betere prestaties en eenvoudigere website-implementatie. Ze optimaliseren ook het laden van code door de grootte te verkleinen en de browsersnelheid te verbeteren.

Het bouwen van betere code met TypeScript

Het omarmen van TypeScript als een JavaScript-ontwikkelaar opent mogelijkheden voor het schrijven van meer robuuste en onderhoudbare code. Door de basisprincipes en kernconcepten te begrijpen die in deze gids worden beschreven, kunt u het statische type-systeem van TypeScript benutten om fouten vroeg in de ontwikkeling te detecteren, wat leidt tot minder bugs en soepeler onderhoud van de code.

Door TypeScript te gebruiken, kunnen JavaScript-ontwikkelaars de kwaliteit en productiviteit van hun code verbeteren. Naarmate je blijft verkennen en oefenen met TypeScript, zul je nog krachtigere functies en mogelijkheden ontdekken.

Blijf je grenzen verleggen en duik dieper in de wereld van TypeScript. 😉