Typescript generics
Created By: chatGPT
TypeScript generics enable you to create reusable components and functions that can work with a variety of data types. This provides flexibility and type safety in your code, as you can define a placeholder type that gets replaced with a concrete type when the function or class is used. Below is a simple example of defining a generic function:
function identity<T>(arg: T): T {
return arg;
}
const stringIdentity = identity<string>('Hello, World!');
const numberIdentity = identity<number>(42);
In the example above,
<T>
represents a type variable that can be replaced with any type. When you call the function, you can explicitly specify the type or let TypeScript infer it based on the argument provided.const inferredIdentity = identity('TypeScript'); // Type is inferred as string
You can also create generic interfaces and classes to achieve similar results. Here’s how to define a generic interface:
interface GenericIdentityFn<T> {
(arg: T): T;
}
const myIdentity: GenericIdentityFn<number> = function (arg) {
return arg;
};
In this example, we defined an interface
GenericIdentityFn
that describes a function taking an argument of type T
and returning the same type. This allows you to create multiple implementations for different types while adhering to the same contract.const myStringIdentity: GenericIdentityFn<string> = function (arg) {
return arg;
};
You can also create classes with generics. Below is an example of a generic class that represents a box containing a value of any type:
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
const numberBox = new Box<number>(123);
const stringBox = new Box<string>('TypeScript Generics');
In this class,
Box<T>
can hold any type of value while maintaining type safety. When you create an instance of Box
, you specify the type so that the getValue
method knows the return type correctly.const retrievedNumber = numberBox.getValue(); // Type inferred as number
const retrievedString = stringBox.getValue(); // Type inferred as string
Constraints can also be applied to generics using
In this case, the function extends
. This allows you to limit the types that can be substituted for a generic type. Here is an example:function loggingIdentity<T extends { length: number }>(arg: T): T {
console.log(arg.length); // Now we can use 'length'
return arg;
}
loggingIdentity([1, 2, 3]); // Valid
loggingIdentity('Hello!'); // Valid
// loggingIdentity(3); // Error: number doesn't have a .length
loggingIdentity
accepts any type T
that has a length
property. This adds yet another layer of type safety to your generics, ensuring that you can only operate on suitable types.