Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to check for type equality in Typescript?

Tags:

typescript

I'd like to get an error if two types don't match. I have an object:

const ACTIVITY_ATTRIBUTES = {
    onsite: {
        id:  "applied",
        ....
    },
    online: {
        id: "applied_online",
        ....
    },
    ...
} as const

I'd like it to be limited to the strings the server can accept

export type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

I know as const can't go with a type limitation (as const will be ignored). But is there a way to to check for type equality, to enforce that the id property is of type ContactAttribute? Something like:

$Values<typeof ACTIVITY_ATTRIBUTES >["id"] === ContactAttribute
like image 775
Ben Carp Avatar asked Oct 21 '25 07:10

Ben Carp


2 Answers

This could be achieved using a dummy validating function.

const validateType = <T> (obj:T) => undefined 

All that is left is to call it with the type and object:

type ContactAttribute = "applied" | "applied_online" | "donated" | "messaged" | "reviewed"

type ActivityAttributes= {
   [k:string]: {
      id: ContactAttribute 
   }
}

const ACTIVITY_ATTRIBUTES = {
    onsite: {
        id:  "applied",
        ....
    },
    donation: {
        id: "donated",
        ....
    },
    ...
} as const

validateType<ActivityAttributes>(ACTIVITY_ATTRIBUTES) // Will show an error if types don't match. 
like image 116
Ben Carp Avatar answered Oct 23 '25 00:10

Ben Carp


I'd come up with a helper function that only accepts arguments whose properties have an id property of type ContactAttribte, and returns its argument untouched, and without changing its type:

const hasGoodContactAttributes =
    <T extends Record<keyof T, { id: ContactAttribute }>>(t: T) => t;

Then you'd create ACTIVITY_ATTRIBUTES like this:

const ACTIVITY_ATTRIBUTES = hasGoodContactAttributes({
    onsite: {
        id: "applied",
        otherProp: 123,
    },
    donation: {
        id: "donated",
        alsoOtherProp: 456
        //....
    },
    online: {
        id: "applied_online",
        //....
    },
    reviewe: {
        id: "reviewed",
        //....
    },
}); // as const if you want

If you make a mistake, you'll get an error:

const BAD_ATTRIBUTES = hasGoodContactAttributes({
    okay: {
        id: "messaged"
    },
    oops: {
        id: "reviewed_online" // error!
    //  ~~ <-- '"reviewed_online"' is not assignable to type 'ContactAttribute'
    }
})

Okay, hope that helps; good luck!

Link to code

like image 28
jcalz Avatar answered Oct 22 '25 23:10

jcalz