Sean
Sean

Reputation: 655

Checking if an object has a key with a type predicate

I have a situation that I think needs a type predicate or "narrowing"?

const obj1 = { foo: 123 }
const obj2 = { bar: 456 }

type ObjKey = keyof typeof obj1 | keyof typeof obj2
function getVal(key: ObjKey) {
  return key in obj1 ? obj1[key] : obj2[key]
}

That doesn't work, do I put a "type guard" on a checking function? Not sure how to write that example:

function objHasKey(obj: object, key: string) {
  return obj.hasOwnProperty(key)
}
function getVal(key: ObjKey) {
  return objHasKey(obj1, key) ? obj1[key] : obj2[key]
}

Upvotes: 2

Views: 1125

Answers (1)

kaya3
kaya3

Reputation: 51037

Sure, you can write a user-defined type guard like this:

function objHasKey<T>(obj: T, key: PropertyKey): key is keyof T {
  return Object.prototype.hasOwnProperty.call(obj, key);
}

Note that Object.prototype.hasOwnProperty.call(obj, key) is almost always preferable to obj.hasOwnProperty(key) because if you don't know what properties an object has, then you don't know for sure that it inherits the hasOwnProperty property from Object.prototype. If you write obj.hasOwnProperty(key), then the compiler will actually complain that T doesn't have a hasOwnProperty method, which is kind of accurate for this reason.

Playground Link

Upvotes: 8

Related Questions