Dakito
Dakito

Reputation: 387

How to check if my property exists in type

As far as we know typescript allow us to declare partially types but what when we gonna to check if my property is in keyof Type. Let's see

interface Car {
   Brand: string;
   Model: string;
}

type KeyofCar = keyof Car; // Brand, Model

if('Brand' is in KeyofCar) {
   something...
} // I know it doesn't work but it is pseudocode

Is there any way to find out that?

Upvotes: 10

Views: 22954

Answers (3)

Justin Toman
Justin Toman

Reputation: 267

I'm not sure what you're going for here. In your question you know at compile time that 'Brand' is in keyof Car. So why would you check for it?

I could imagine trying to do something like that if the type is not completely known, like in a type argument...

function<T>(foo: T) {
  // this is not possible because keyof does not exist in runtime contexts
  if('bar' in keyof T) {
    // do something...
  }
}

I would say you wouldn't try to solve the problem by comparing something to keyof T. Instead try to do something like this

interface Car {
  Brand: string;
  Model: string;
}

interface Bus {
  Passengers: number;
  Color: string;
}

function(foo: Car | Bus) {
  if('Brand' in foo) {
    // foo is a Car
  } else {
    // foo is a Bus
  }
}

If you really want to do something with the keys you could do something like this

type CarKey = keyof Car;
const carKeys: CarKey[] = ['Brand', 'Model'];

function(key: string) {
  if(carKeys.includes(key)) {
    // do thing
  }
}

Or to be even more sure that you have every key

type CarKey = keyof Car;
const carKeys = Object.keys({
    Brand: null, 
    Model: null
} satisfies Record<CarKey, null>) as Array<keyof Car>;

function isKeyOfCar(key: string): key is CarKey {
    return carKeys.includes(key);
}

That way if the Car type changes over time, you'll know if these keys need to be updated.

Upvotes: 4

codelovesme
codelovesme

Reputation: 3267

type CheckPropExists<T extends {[x:string]:any},Prop extends string> = T[Prop] extends undefined ? false : true;
//Example
type Result = CheckPropExists<{a:string;b:number;},"a">;
//Result is true

Upvotes: 0

DeeV
DeeV

Reputation: 36045

As of this writing, there isn't a way to check for this at runtime strictly using Typescript mechanisms. Though a kinda ugly hack you can do is create a Record then extract the keys from it.

interface Car {
   Brand: string;
   Model: string;
}

const carRecord: Record<keyof Car, boolean> = {
  Brand: true,
  Model: true
}

if (carRecord['Brand']) {
  something...
}

The reason you do a Record is because every time you change the interface, you must also change the Record. Otherwise, Typescript will throw compile errors. At the very least this ensures that the check will remain consistent as the Car interface grows.

Upvotes: 3

Related Questions