5 Typescript tips to save your day
Published: 2023-11-02 00:12:57

Hey TypeScript enthusiasts! In this post, we'll explore some tips that might be very useful in your daily tasks. 

## 1. Template Literal Types

You can use template literal types to create complex and calculated types.

```ts
type Color = "red" | "green" | "blue";

type CSSColor = `bg-${Color}`; // Template literal type

const redBackground: CSSColor = "bg-red";
const greenBackground: CSSColor = "bg-green";
const blueBackground: CSSColor = "bg-blue";

// This will trigger a type error:
const invalidColor: CSSColor = "bg-yellow";

```

In this example, we create a type **CSSColor** using a template literal type. It allows us to define CSS class names based on known colors. Attempting to assign an invalid color like "bg-yellow" will result in a type error, ensuring type safety.

## 2. Nullish Coalescing Operator

The nullish coalescing operator **(??)** provides a default value for a variable only if the variable is **null** or **undefined**.

```ts
const userSettings = {
  theme: "light",
  showNotifications: null,
};

const theme = userSettings.theme ?? "default";
const notifications = userSettings.showNotifications ?? true;

console.log(theme);  // "light"
console.log(notifications);  // true

```

In this example, we use the **(??)** operator to set default values for theme and notifications. It ensures that we only fall back to the default value if the original value is explicitly **null** or **undefined**, not for other falsy values like an empty string or false.

## 3. Mapped Types

We can use mapped types to create new types by transforming or modifying the properties of an existing type.

```ts
interface User {
  id: number;
  name: string;
  email: string;
}

type ReadonlyUser = {
  readonly [K in keyof User]: User[K];
};

const user: ReadonlyUser = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
};

// This will trigger a type error:
user.name = "Bob";

```

In this example, we define a **ReadonlyUser** type using a mapped type. It makes all properties of User **readonly**, preventing modifications after initialization. This is a simple example, but mapped types can be used for more complex transformations and combinations of types.

## 4. Tuple Types

Tuple types can define arrays with a fixed number of elements of specific types.

```ts
type Point = [number, number];

const origin: Point = [0, 0];
const position: Point = [2, 4];

// This will trigger a type error:
const invalidPoint: Point = [1, "hello"];

```

In this example, we define a Point type as a tuple with two elements, both of type number. This allows us to create arrays with a fixed structure, ensuring that the number and types of elements are correct.

## 5. Pick Utility Type

Utilize the Pick utility type to select specific properties from an object type.

```ts
type User = {
  id: number;
  name: string;
  email: string;
  age: number;
};

type UserProfile = Pick<User, "name" | "email">;

const user: User = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
  age: 30,
};

const profile: UserProfile = { name: user.name, email: user.email };

```

For this example, we use the **Pick** utility type to create a **UserProfile** type that includes only the "name" and "email" properties from the User type. This is useful when you want to create a smaller object with a subset of properties.

Here you have it, 5 great tips to help with your Typescript code.

If you enjoy this content, leave a reaction!
Thanks!

Happy Coding! :rocket: