DEV Community

vinodchauhan7
vinodchauhan7

Posted on

Typescript Generics Quick Intro with react basics

In this article, we're going to look over how Generics work in Typescript. Literally, it looks scary at the beginning but when we understand and breaks the overall logic of generics in chunks then they will become our best friends.

This article needs some basic understanding of typescript to advance further.

Array in typescript

Most basic type of generics we always use is defining array of particular type. For instance:number[],string[],boolean[];

type numArr = Array<number>;
type strArr = Array<string>;
type boolArr = Array<boolean>;

let numberArray: numArr = [1, 2, 3, 4];
let stringArray: strArr = ["H", "e", "l", "l", "o"];
let boolArray: boolArr = [true, false, true];

console.log(numberArray);
console.log(stringArray);
console.log(boolArray);

If we not pass any particular type then it will show error on screen like below pic.

Alt Text

Generic Methods

Suppose we need a method which can return middleElement of any array type passed to it. So most basic approach to find middleElement will be like this :

const middleElement = (arr: Array<any>) => {
  return arr[Math.floor(arr.length / 2)];
};

let numberArray: numArr = [1, 2, 3, 4, 5];

let stringArray: strArr = ["I", "T", "A", "L", "Y"];

let boolArray: boolArr = [true, false, true];

let middle1 = middleElement(numberArray);

let middle2 = middleElement(stringArray);

let middle3 = middleElement(boolArray);

console.log(middle1); //3
console.log(middle2); //A
console.log(middle3); //false

But in this way, we will loose the TypeDefinition of the return type of method as you can see in below pic which shows 'any' when we hover over it.
Alt Text

Now if we implement generics feature of typescript then we can retain the typeDefinition of the method.

const middleElement = <T>(arr: Array<T>) => {
  return arr[Math.floor(arr.length / 2)];
};

Alt Text

We can see in above pic, when we hover over any middleElement method of certain type, we see its argument passed type & its return type.

//We can explicitly define type of our method as below :
let middle2 = middleElement<string>(stringArray);
To make a method which can accept more than one generic type we can do the following :
//This method will accept any type of arguments and make a combined object of it.
const makeObj = <X, Y>(x: X, y: Y) => {
  return { x, y };
};

let numbArray: numArr = [1, 2, 3, 4];

let Obj = { firstName: "Vinod", lastName: "Chauhan" };

let newObj = makeObj(numbArray, Obj);

console.log(newObj);

Alt Text

We can see the return type of makeObj method in above pic, this shows the power of generics with VS Code editor.

Generic Method with required fields

Let say we need a method 'makeICardDetail' which takes an object as a parameter. This object required firstname,LastName,age as a mandatory fields to fullfill its requirement. So one way of doing this will be :

const makeICardDetail = (obj: {
  firstName: string;
  lastName: string;
  age: number;
}) => {
  return {
    ...obj, //Copy other contents of Object as it is.
    ICard: obj.firstName + " " + obj.lastName + ", " + obj.age
  };
};

let makeNewDetail = makeICardDetail({
    firstName: "Vinod",
    lastName: "Chauhan",
    age: 27
  });
console.log(makeNewDetail.ICard); //Vinod Chauhan, 27

Now, What if I need to pass location also but not as a mandatory field. If I pass location field in makeICardDetail as a argument, typescript compiler gives me error on it.

let makeNewDetail = makeICardDetail({
  firstName: "Vinod",
  lastName: "Chauhan",
  age: 27,
  location: "India"
});
console.log(makeNewDetail.ICard); //Vinod Chauhan, 27

//TSC compiler
index.ts:59:3 - error TS2345: Argument of type '{ firstName: string; lastName: string; age: number; location: string; }' is not assignable to parameter
of type '{ firstName: string; lastName: string; age: number; }'.
  Object literal may only specify known properties, and 'location' does not
exist in type '{ firstName: string; lastName: string; age: number; }'.

59   location: "India"
     ~~~~~~~~~~~~~~~~~

[9:01:00 PM] Found 1 error. Watching for file changes.

Here Generics come to rescue us with its 'extends' feature.

const makeICardDetail = <T extends { firstName: string; lastName: string; age: number }>( obj: T) => {
  return {
    ...obj,
    ICard: obj.firstName + " " + obj.lastName + ", " + obj.age
  };
};

And if you look at below pic, you can see 'makeNewDetail' variable gives option of all possible values in it which help us in complex and lengthy application.
Alt Text

Interface with Generics

interface KeyPair<T, U> {
  key: T;
  value: U;
}

let kv1: KeyPair<number, string> = { key: 1, value: "Vinod" }; // OK
let kv2: KeyPair<number, number> = { key: 2, value: 12345 }; // OK

Generics in React

If you have ever worked on React with typescript, you must have implemented functional components where 'props' has to be passed. props provide typedefinition to components.

import React from "react";

interface Props {
  name: string;
}

export const Example: React.FC<Props> = ({ name }) => {
  return <div>Hello {name}</div>;
};

In above snippet, "React.FC" props are passed as generic to it which is type of interface where fields have there type declared with them.

Also we can define generics with useState.

export const Example: React.FC<Props> = ({name}) => {
//const [state] = React.useState({fullName:"",age:0});
    const [state] = React.useState<{fullName:string | null;age : number}>({fullName : "",age:0});
  return <div>Hello {name}</div>;
};

I hope this article will add a small amount of knowledge in your react learning with typescript.

Top comments (4)

Collapse
 
mintuz profile image
Adam Bulmer

Great article and a complex topic broken down well.

I found this the other day which has also been quite helpful. github.com/typescript-cheatsheets/...

Collapse
 
nikhilknoldus profile image
Nikhil

This article is good, covered a good part of TypeScript.
It would be great to know more about React with TypeScript.

Thanks!

Collapse
 
vinodchauhan7 profile image
vinodchauhan7

Sure Nikhil, Will get back soon with it.

Collapse
 
ovieokeh profile image
Ovie Okeh

Really nice article. In the case of adding an optional field, you could also use an index signature to specify optional fields.