Typescript Advanced APIs

SATYASATYA
4 min read

Hello Readers, this blog explains some of the Typescript advanced apis. If you are already familiar with typescript, knowing these advanced apis will unlock much more potential for you to write better code.

Before diving into the main topic, first let' s set up a new Typescript project.


npm init

tsc --init


Now you are ready to read, write and test the code in your code editor.

  1. Pick

Pick is used when we as a developer wants to pick values from types | interface as a props. Now let's us understand this with an example.

interface User {
    id : number;
    name : string;
    email : string;
    password: string;
    age : number;
}

type updateProps = Pick< User , 'name' | 'age' | 'password' > // we can Pick values from type as well as interface. 

// Update user details

const updateUser = (updatedProps: updateProps) => {

// logic

}

Look at this code above, we have defined an interface User which has some fields, now we want to update the user details, but we don't want the id and email to be updated.

So for that same reason we use Pick and we can easily pick field from user to be passed to a function as a prop and updated.

  1. Partial

Now let us imagine a condition where user wants to update name and password but not age. So for this use case we can use Partial

type updatePropsPartial = Partial<updateProps>

In the above code the Partial keyword justifies a condition the props may or may not be given, meaning they are not mandatory.

  1. Readonly

There are some case scenarios that if we have code to hit some endpoint , using an api key. And if the developer by mistakes changes something in the api key or endpoint the code will fail.

So for this reason we use readonly

interface Config {
    readonly endpoint : string;
    readonly apikey : string;
}

const config : Readonly<Config> => { //Alternate method makes whole object Readonly rather than doing manually to all object 

    endpoint : 'https://api.example.com',
    apikey : 'adfaf32e24jljkj342'
}

In the code above we defined an interface which has endpoint and apikey as it's field. And in the next line we use Readonly to make it as constant.

But it may raise a doubt in your mind that it can be done using const keyword, but no. We can change it as follows (Which is not to be done)

const config : Config => { 
        endpoint : 'https://api.example.com',
        apikey : 'adfaf32e24jljkj342'
    }

config.endpoint = 'https://api/something.com'

to make this above code not possible, we use readonly | Readonly

  1. Record

Record defines a cleaner way to write key-value pair.

type Users = Record<string, {age : number, name : string}>

const users : Users = {
    '345@32' : {name : "satya", age : 20},
    '346@32' : {name : "ankur", age : 21},
}

In the above code we defined a type Users using Record which specifies that firstly it has a key of type string and then it has an object which has age and name as its fields.

  1. Map

Map provides us another way to write key-value pairs in typescript.

interface Customer {
    name : string;
    age : number;
}

const customer = new Map< string, Customer>();

customer.set("1224", {name : "satya", age : 20});
customer.set("1235", {name : "somil", age : 21});

customer.get("1224")
customer.delete("1224")

In the code above we defined an interface and then used it to define a type of customer, Which looks exactly similar to Record .

In addition, Map provides some functions like

  • set ()

  • get ()

  • delete()

  1. Exclude

The name itself explains what it will do. It excludes a few options from the given options.

type EventType = 'click' | 'scroll' | 'mousemove';
type ExcludeEvent = Exclude<EventType , 'scroll'>; // click , mousemove

const handleEvent = (event : ExcludeEvent) => {
    console.log(`Handling event ${event}`);
}

handleEvent('click')

In the above code snippet, we have excluded the type scroll from the EventType which consists of scroll, click, mousemove as options to be passed to a function.

now we cannot pass scroll to handleEvent.

  1. Type Inference in zod

To understand this section we will directly get into the code part.

import { z } from 'zod';
import express from "express";

const app = express();

// Define the schema for profile update

const userProfileSchema = z.object({
    name: z.string().min(1, { message: "Name cannot be empty" }),
    email: z.string().email({ message: "Invalid email format" }),
    age: z.number().min(18, { message: "You must be at least 18 years old"}).optional(),
});

type FinalUserSchema = z.infer<typeof userProfileSchema>; // The thing to learn

app.put("/user", (req, res) => {
    const { success } = userProfileSchema.safeParse(req.body);
    const updateBody : FinalUserSchema = req.body; // how to assign a type to updateBody?

    if (!success) {
        res.status(411).json({});
        return
    }

    // update database here
    res.json({
        message: "User updated"
    })
});

app.listen(3000);

In the code above to give the function a type (updateBody) we used type inference in zod which FinalUserSchema infers the types and fields from userProfileSchema.

Thankyou for reading the blog. If you found this helpful, like and leave your thoughts on comments below.

0
Subscribe to my newsletter

Read articles from SATYA directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

SATYA
SATYA

Satya Prakash Dwivedi, a self-taught web developer and student, is passionate about creating beautiful and functional web experiences. He contributes to open-source projects and enjoys educating school students.