Generics Flashcards

1
Q

What is a generic type?

A

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];
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is the syntax of a generic type?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How do you use a generic type?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

How do you use generic types in a call signature?

A

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
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How do you define an interface with generics?

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you define a class with generics?

A

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");
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

How can you constrain a generic type?

A

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'
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How can you use type parameters in generic constraints?

A

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"'.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How can you use class types in generics?

A

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;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly