Skip to content

Latest commit

 

History

History
72 lines (51 loc) · 2.83 KB

generics.md

File metadata and controls

72 lines (51 loc) · 2.83 KB

Generics in TypeScript provide a way to create flexible and reusable code components that can work with a variety of data types, reducing code redundancy. They are particularly useful when you want to create a component that can handle different types of data.

Use Cases:

  1. Generic Functions:
// A generic function named 'genericFn' that can work with any type 'T'.
function genericFn<T>(arg: T): T {
    return arg;
}

let output1 = genericFn<string>("myString");  // type of output will be 'string'
let output2 = genericFn<number>(100);  // type of output will be 'number'

Use Case: Generic functions are useful when you want to apply the same logic to different data types. In the example above, genericFn can accept any type of argument and return a value of the same type.

  1. Generic Interfaces:
// A generic interface that describes a function.
interface UsefulFunction<T> {
    (input: T): T;
}

// The 'usefulFn' function implements the 'UsefulFunction' interface.
let myUsefulFunction: UsefulFunction<number> = usefulFn;

Use Case: Generic interfaces can be used to define a contract for classes or functions that can work with different data types. In the example above, UsefulFunction describes a function that takes an input of type T and returns a value of the same type.

  1. Generic Classes:
// A generic class 'GenericNumber' that works with a set of types.
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

Use Case: Generic classes are useful when you want to create a class that can work with different data types. In the example above, GenericNumber can work with any numeric type.

  1. Generic Constraints:
// A generic function 'getProperty' with a constraint that 'T' must have a property 'K'.
function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.

Use Case: Generic constraints allow you to limit the types that can be used with a generic function, class, or interface. In the example above, getProperty can only be used with objects that have a property of type K.

Pros of Generics:

  • Code reusability: Generics allow you to write a piece of code once and reuse it with different data types.
  • Type safety: Generics provide compile-time type checking, reducing runtime errors.

Cons of Generics:

  • Complexity: Generics can make the code more complex and harder to understand for beginners.
  • Debugging: Debugging generic code can be challenging because the actual type is not known until runtime.