Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript check if object matches type

Tags:

typescript

I have the following problem. Let's say I have a type:

type A = {
    prop1: string,
    prop2: {
        prop3: string
    }
}

I am receiving some json object from an external service and I want to validate if that json matches type A:

function isA(obj:any): boolean {
    // What should be here?
}

So if my obj is something like:

{
 prop1: "Hello",
 prop2: {
    prop3: "World"
 }
}

or

{
     prop1: "Hello",
     prop2: {
        prop3: "World"
     },
     moreProps: "I don't care about"
}

The function would return true, but false for something like

{
     foo: "Hello",
     bar: {
        prop3: "World"
     }
}

What's the easiest way to achieve this?

Thanks.

like image 473
mario595 Avatar asked May 17 '19 15:05

mario595


1 Answers

  1. Use a type-guard so that Typescript will also narrow the type at type-checking time for you

To use a type-guard, you should change the return type of your isA function to be obj is A

Overall that should make your type validation function look like:

function isA(obj: unknown): obj is A {
    // return boolean here
}
  1. Use the typeof operator to check properties

typeof will return a string value telling you what the type of a variable is. (docs)

In this case, for A you can do something like:

function isA(obj: unknown): obj is A {
    return (
        obj &&
        typeof obj === 'object' &&
        typeof obj['prop1'] === 'string' &&
        obj['prop2'] &&
        typeof obj['prop2'] === 'object' &&
        typeof obj['prop2']['prop3'] === 'string'
    );
}

It's not the most readable thing in the world, and you could always break it down to it's component pieces and comment each check if you'd like.

One important thing to note, however, is that typeof null is actually 'object' so you can't simply check if typeof obj['prop2'] === 'object' and then move on, you'll need to also check if it exists since it still could be null.

At this point, not only will you be validating correctly at runtime, but TypeScript will now be able to improve its type-checking by narrowing the type of obj to A when isA returns true.

like image 130
casieber Avatar answered Nov 15 '22 06:11

casieber