Generics Flashcards
What is a generic type?
A generic type is a type that is defined with one or more type parameters, which can be used to make the type more flexible and reusable. Generics allow you to write code that works with a variety of data types without having to repeat the code for each type.
Here is an example of a generic type in TypeScript:
interface Array<T> { length: number; [index: number]: T; }
By using a generic type like this, you can create arrays of different types, such as an array of strings, an array of numbers, or an array of objects that conform to a certain interface. For example:
const names: Array<string> = ["Alice", "Bob", "Charlie"]; const numbers: Array<number> = [1, 2, 3, 4, 5];
“Documentation - Generics” (typescriptlang.org). Retrieved March 31, 2023.
What is the syntax of a generic type?
In TypeScript, the syntax for declaring a generic type is to use angle brackets (<
and >
) to enclose one or more type
parameters separated by commas. Here is the basic syntax for declaring a generic type:
interface MyGenericInterface<T> { // interface members go here }
In this example, T
is the name of the type parameter. The type parameter can be used in any member of the interface to represent a type that is determined at the time the interface is used.
“Documentation - Generics” (typescriptlang.org). Retrieved March 31, 2023.
How do you use a generic type?
To use a generic type, you provide a specific type
argument for the type parameter. Here is an example:
interface Array<T> { length: number; [index: number]: T; } const myObject: MyGenericInterface<string> = { // object members go here };
In this example, string
is the type argument provided for the T
type parameter of the MyGenericInterface
type.
You can also use multiple type parameters in a generic type by separating them with commas. Here is an example:
interface MyGenericInterface<T, U> { // interface members go here }
In this example, T
and U
are two type parameters that can be used to represent different types in the interface. To use this generic type, you would provide two type arguments when you create an instance of the type, like this:
const myObject: MyGenericInterface<string, number> = { // object members go here };
In this example, string is the type argument for the T type parameter, and number is the type argument for the U type parameter.
“Documentation - Generics” (typescriptlang.org). Retrieved March 31, 2023.
How do you use generic types in a call signature?
In TypeScript, you can use generics in call signatures to create functions that can operate on a variety of data types. Here’s an example of a call signature that uses generics:
interface MyFunction { <T>(arg: T): T; }
In this example, MyFunction
is an interface that defines a call signature for a function that takes a single argument of type T
, and returns a value of the same type T
. The type parameter T
is defined between the angle brackets (<
and >
).
To use this interface, you can define a function that conforms to the call signature:
const myFunction: MyFunction = <T>(arg: T): T => { return arg; };
In this example, myFunction
is a function that takes a single argument of type T
and returns a value of the same type T
. The function uses the type parameter T
to define the type of the argument and return value.
You can call this function with a variety of data types, like this:
const result1 = myFunction("hello"); // result1 is of type string const result2 = myFunction(123); // result2 is of type number const result3 = myFunction(true); // result3 is of type boolean
“Generic Types” (typescriptlang.org). Retrieved March 31, 2023.
How do you define an interface
with generics?
Generic interfaces have a comma separated generic type parameter list in angle brackets (<>
) following the name of the interface.
interface MyGenericInterface<T> { value: T; getValue(): T; }
In this example, MyGenericInterface
is an interface
with a single type parameter T
. The interface
defines a value property of type T
and a getValue
method that returns a value of type T
.
“Generic Classes” (typescriptlang.org). Retrieved March 31, 2023.
How do you define a class
with generics?
A generic class has a similar shape to a generic interface. Generic classes have a comma separated generic type parameter list in angle brackets (<>
) following the name of the class.
class MyGenericClass<T> { private value: T; constructor(value: T) { this.value = value; } getValue(): T { return this.value; } }
In this example, MyGenericClass
is a class with a single type parameter T
. The constructor takes a value of type T
as an argument and assigns it to the value property. The getValue
method returns the value property.
To create an instance of this class, you provide a specific type argument for the type parameter T, like this:
const myObject = new MyGenericClass<string>("hello");
“Generic Classes” (typescriptlang.org). Retrieved March 31, 2023.
How can you constrain a generic type?
A generic type parameter can be constraint with the extends
keyword . This allows you to restrict the types that can be used with the generic type parameter.
Here’s an example:
interface MyConstrainedInterface<T extends string> { value: T; getValue(): T; }
In this example, MyConstrainedInterface
is an interface
with a single type parameter T
. The type parameter is constrained to be a subtype of the string
type by using the extends
keyword and specifying string
as the constraint.
This means that when you use MyConstrainedInterface
, the T
type parameter can only be a string
or a subtype of the string
type.
To use this interface, you can define a class that implements it:
class MyInvalidClass implements MyConstrainedInterface<number> { // This generates a compilation error because 'number' is not a subtype of 'string' }
“Generic Constraints” (typescriptlang.org). Retrieved March 31, 2023.
How can you use type parameters in generic constraints?
In TypeScript, you can use type parameters in generic constraints to enforce that the types used in a generic function or class meet certain requirements. You can define a constraint by using the extends
keyword followed by the constraint type.
function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) { return obj[key]; } let x = { a: 1, b: 2, c: 3, d: 4 }; getProperty(x, "a"); getProperty(x, "m"); // Error: Argument of type '"m"' is not assignable to parameter of type '"a" | "b" | "c" | "d"'.
“Using Type Parameters in Generic Constraints” (typescriptlang.org). Retrieved April 3, 2023.
How can you use class types in generics?
In TypeScript, you can use class types in generics to enforce that the generic type conforms to a specific class or has a specific constructor signature. To do this, you’ll need to use a type parameter as a constructor type.
class BeeKeeper { hasMask: boolean = true; } class ZooKeeper { nametag: string = "Mikle"; } class Animal { numLegs: number = 4; } class Bee extends Animal { keeper: BeeKeeper = new BeeKeeper(); } class Lion extends Animal { keeper: ZooKeeper = new ZooKeeper(); } function createInstance<A extends Animal>(c: new () => A): A { return new c(); } createInstance(Lion).keeper.nametag; createInstance(Bee).keeper.hasMask;
“Using Class Types in Generics” (typescriptlang.org). Retrieved April 3, 2023.