Reputation: 655
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
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.
Upvotes: 8