DEV Community

Cover image for 7 Secret TypeScript Tricks Pros Use 😎🤫
Tapajyoti Bose
Tapajyoti Bose

Posted on • Edited on

7 Secret TypeScript Tricks Pros Use 😎🤫

TypeScript is an outstanding tool to make our lives easier & avoiding bugs, yet sometimes feels overwhelming to use.

overwhelm

This article outlines 7 TypeScript tricks that will make your life easier which all pros use.

1. Type Inference

Typescript is smart enough to infer the data types when you help it narrow them down.



enum CounterActionType {
  Increment = "INCREMENT",
  IncrementBy = "INCREMENT_BY",
}

interface IncrementAction {
  type: CounterActionType.Increment;
}

interface IncrementByAction {
  type: CounterActionType.IncrementBy;
  payload: number;
}

type CounterAction =
  | IncrementAction
  | IncrementByAction;

function reducer(state: number, action: CounterAction) {
  switch (action.type) {
    case CounterActionType.Increment:
      // TS infers that the action is IncrementAction
      // & has no payload
      return state + 1;
    case CounterActionType.IncrementBy:
      // TS infers that the action is IncrementByAction
      // & has a number as a payload
      return state + action.payload;
    default:
      return state;
  }
}


Enter fullscreen mode Exit fullscreen mode

As shown above, TypeScript infers the type of the action based on the type property, so you DON'T need to check whether payload exists.

2. Literal Types

Often you need specific values for a variable, that's where literal types come in handy.



type Status = "idle" | "loading" | "success" | "error";


Enter fullscreen mode Exit fullscreen mode

It works for numbers too:



type Review = 1 | 2 | 3 | 4 | 5;

// or better yet:
const reviewMap = {
  terrible: 1,
  average: 2,
  good: 3,
  great: 4,
  incredible: 5,
} as const;

// This will generate the same type as above,
// but it's much more maintainable
type Review = typeof reviewMap[keyof typeof reviewMap];


Enter fullscreen mode Exit fullscreen mode

3. Type Guards

Type guards are another method to narrow down the type of a variable:



function isNumber(value: any): value is number {
  return typeof value === "number";
}

const validateAge = (age: any) => {
  if (isNumber(age)) {
    // validation logic
    // ...
  } else {
    console.error("The age must be a number");
  }
};


Enter fullscreen mode Exit fullscreen mode

NOTE: In the example above, it's better to use:



const validateAge = (age: number) => {
  // ...
};


Enter fullscreen mode Exit fullscreen mode

The example was a simplification to show how type guards work.

4. Index Signature

When you have dynamic keys in an object, you can use an index signature to define its type:



enum PaticipationStatus {
  Joined = "JOINED",
  Left = "LEFT",
  Pending = "PENDING",
}

interface ParticipantData {
  [id: string]: PaticipationStatus;
}

const participants: ParticipantData = {
  id1: PaticipationStatus.Joined,
  id2: PaticipationStatus.Left,
  id3: PaticipationStatus.Pending,
  // ...
};


Enter fullscreen mode Exit fullscreen mode

5. Generics

Generics are a powerful tool to make your code more reusable. It allows you to define a type that will be determined by the use of your function.

In the following example, T is a Generic type:



const clone = <T>(object: T) => {
  const clonedObject: T = JSON.parse(JSON.stringify(object));
  return clonedObject;
};

const obj = {
  a: 1,
  b: {
    c: 3,
  },
};

const obj2 = clone(obj);


Enter fullscreen mode Exit fullscreen mode

6. Immutable Types

You can make your types immutable by adding as const. This ensures that you don't end up accidentally changing the values.



const ErrorMessages = {
  InvalidEmail: "Invalid email",
  InvalidPassword: "Invalid password",
  // ...
} as const;

// This will throw an error
ErrorMessages.InvalidEmail = "New error message";


Enter fullscreen mode Exit fullscreen mode

7. Partial, Pick, Omit & Required Types

Often while working with server & local data, you need to make some properties optional or required.

Instead of defining hundreds of interfaces with slightly altered versions of the same data. You can do that using Partial, Pick, Omit & Required types.



interface User {
  name: string;
  age?: number;
  email: string;
}

type PartialUser = Partial<User>;
type PickUser = Pick<User, "name" | "age">;
type OmitUser = Omit<User, "age">;
type RequiredUser = Required<User>;

// PartialUser is equivalent to:
// interface PartialUser {
//   name?: string;
//   age?: number;
//   email?: string;
// }

// PickUser is equivalent to:
// interface PickUser {
//   name: string;
//   age?: number;
// }

// OmitUser is equivalent to:
// interface OmitUser {
//   name: string;
//   email: string;
// }

// RequiredUser is equivalent to:
// interface RequiredUser {
//   name: string;
//   age: number;
//   email: string;
// }


Enter fullscreen mode Exit fullscreen mode

And of course, you can use intersection to combine them:



type A = B & C;


Enter fullscreen mode Exit fullscreen mode

Where B & C are any types.

That's all folks! 🎉

Finding personal finance too intimidating? Checkout my Instagram to become a Dollar Ninja

Resources used

  1. Freepik
  2. Giphy

Thanks for reading

Need a Top Rated Front-End Development Freelancer to chop away your development woes? Contact me on Upwork

Want to see what I am working on? Check out my Personal Website and GitHub

Want to connect? Reach out to me on LinkedIn

Follow me on Instagram to check out what I am up to recently.

Follow my blogs for bi-weekly new Tidbits on Dev

FAQ

These are a few commonly asked questions I get. So, I hope this FAQ section solves your issues.

  1. I am a beginner, how should I learn Front-End Web Dev?
    Look into the following articles:

    1. Front End Development Roadmap
    2. Front End Project Ideas
  2. Would you mentor me?

    Sorry, I am already under a lot of workload and would not have the time to mentor anyone.

Top comments (23)

Collapse
 
mistval profile image
Randall

Nice tips. In my opinion the main thing that separates pros from newbies is that pros turn on all the strict options and still manage to avoid as like the plague because they know a ton of tools like these to avoid it. Death to as!

Collapse
 
insidewhy profile image
insidewhy

It's now generally recommended to write index signatures using Record e.g. type ParticipantData = Record<string, ParticipantStatus>.

Collapse
 
bennycode profile image
Benny Code

Great tips! I'd like to contribute one more suggestion. Instead of using "any" for typing inputs in your type guard, it's safer to use "unknown". This approach encourages you to first check if a parameter is of type object before accessing its properties. You can see this here: youtube.com/watch?v=p-YEN-9KnRo

Collapse
 
bretbernhoft profile image
Bret Bernhoft

This is a nice summary of TypeScript tricks. Thank you for putting it together.

Using TypeScript has changed my approach to programming for the Web. And I'm grateful to have access to this technology.

Collapse
 
ghulamhussainsoftware profile image
GhulamHussainJoyo

I was looking for this type of article. Where I can learn all about props types. Thanks for sharing

Collapse
 
michthebrandofficial profile image
michTheBrandofficial

Hello. Do you mean React prop types? What prop types exactly?

Collapse
 
zflxw profile image
Maik

Thank you for these tips. Especially the Partial, Pick, Omit & Required Types help me, as I only knew Partial<>, but I have a usecase for the other ones too.

Collapse
 
brense profile image
Rense Bakker

Very good article and examples! :)

Collapse
 
yusufkolawole profile image
Yusuf Kolawole

Nice collections, thanks for listing all these...

Collapse
 
reacthunter0324 profile image
React Hunter

Great

Collapse
 
h_sifat profile image
Muhammad Sifat Hossain

Wow, I didn't know that I had been a TS Pro all this time!