Generics i TypeScript
Denne artikel forklarer generics i TypeScript.
YouTube Video
Generics i TypeScript
Generics i TypeScript er en funktion, der gør det muligt at definere genbrugelige og typesikre funktioner, klasser og interfaces ved at parameterisere typer. Ved at bruge generics kan du skrive kode, der ikke afhænger af specifikke typer, hvilket gør det muligt at udføre de samme operationer på forskellige typer.
Grundlæggende om generics
Generics fungerer som skabeloner, der accepterer typer som argumenter, hvilket gør det muligt for funktioner og klasser at håndtere forskellige typer.
Generiske funktioner
Følgende er et eksempel på en funktion med dens argumenttyper specificeret ved hjælp af generics.
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity<number>(42)); // 42
6console.log(identity<string>("Hello")); // Hello
T
er et generisk typeargument, der repræsenterer typerne for funktionens argumenter og returværdi. Den faktiske type bestemmes, når funktionen kaldes.- Ved eksplicit at angive
<number>
eller<string>
specificerer du typen.
Generiske typer fungerer uden eksplicit specificering, fordi TypeScript udfører typeinferens.
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity(42)); // 42
6console.log(identity("Hello")); // Hello
Begrænsninger på generics
Ved at sætte begrænsninger på generics kan du begrænse dem til kun at acceptere specifikke typer.
1function loggingIdentity<T extends { length: number }>(arg: T): T {
2 console.log(arg.length);
3 return arg;
4}
5
6loggingIdentity("Hello"); // 5
7loggingIdentity([1, 2, 3]); // 3
8
9// loggingIdentity(42); // Error: number does not have a length property.
- Ved at angive
T extends { length: number }
indikerer du, atT
skal være en type med enlength
-egenskab. Derfor vil typer uden enlength
-egenskab ikke blive accepteret.
Generiske klasser
Klasser kan også defineres ved hjælp af generics. Generiske klasser tilbyder fleksible typer til egenskaber og metoder.
1class Box<T> {
2 private _value: T;
3
4 constructor(value: T) {
5 this._value = value;
6 }
7
8 public getValue(): T {
9 return this._value;
10 }
11
12 public setValue(value: T): void {
13 this._value = value;
14 }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue()); // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue()); // Hello
Box<T>
deklarerer typenT
, der bruges inden for klassen som en generisk type. Dette gør det muligt at genbruge den samme klasse til forskellige typer.
Generiske interfaces
Generics kan også bruges sammen med interfaces.
1interface Pair<T, U> {
2 first: T;
3 second: U;
4}
5
6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
7console.log(numberStringPair); // { first: 1, second: 'One' }
8
9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair); // { first: true, second: [ 1, 2, 3 ] }
- Ved at angive to generiske typer med
Pair<T, U>
kan du definere et objekt med en kombination af forskellige typer.
Standard Type Argumenter
Det er også muligt at angive en standardtype for generiske typeargumenter.
1function createArray<T = string>(length: number, value: T): T[] {
2 return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a")); // ['a', 'a', 'a']
6console.log(createArray(3, 100)); // [100, 100, 100]
- Vi indstiller standardtypeargumentet til
string
med<T = string>
. Hvis ingen type er angivet eksplicit, vilT
være af typenstring
.
Generiske Typealiasser
Generiske typer kan også bruges som typealiasser (type
).
1type Result<T> = {
2 success: boolean;
3 data: T;
4};
5
6const successResult: Result<number> = { success: true, data: 42 };
7const errorResult: Result<string> = { success: false, data: "Error occurred" };
8
9console.log(successResult); // { success: true, data: 42 }
10console.log(errorResult); // { success: false, data: 'Error occurred' }
Result<T>
repræsenterer et resultatobjekt, der indeholder data af typenT
. På denne måde kan du oprette fleksible typealiasser ved hjælp af generics.
Flere Generiske Typer
Ved at bruge flere generiske typer kan du definere endnu mere alsidige funktioner og klasser.
1function merge<T, U>(obj1: T, obj2: U): T & U {
2 return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged); // { name: 'Alice', title: 'Engineer' }
merge
-funktionen tager to forskellige typer,T
ogU
, og kombinerer dem for at returnere et nyt objekt.
Sammendrag
- Generics gør det muligt at skrive genbrugelig og typesikker kode ved at behandle typer som parametre.
- Ved at bruge generics i funktioner, klasser og interfaces kan du skrive fleksibel logik, der håndterer forskellige typer.
- Ved at tilføje begrænsninger til typeargumenter eller angive standardtypeargumenter, kan du kontrollere, hvordan generics bruges.
Ved hjælp af generics kan du skrive typeuafhængig og generel kode, der udnytter TypeScripts kraftfulde typesystem fuldt ud.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.