Take this code:
const lookup = {
foo: 1,
bar: 2
}
const getValueOrDefault = (name: string, defaultValue: number) => {
if (name in lookup) {
return lookup[name] // ERROR
}
return defaultValue
}
The lookup[name]
expression causes this TS error (playground):
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ foo: number; bar: number; }'.
No index signature with a parameter of type 'string' was found on type '{ foo: number; bar: number; }'.
...even though I did if (name in lookup)
to check it first. I tried hasOwnProperty
, and that doesn't work either.
TypeScript is often smart about refining types within conditional blocks, but not here. Why? And how can I make it work (without just hacking it by relaxing the type of lookup
)?
You can wrap the name in lookup
check in type guard to help typescript to understand that once condition is true - name
is valid lookup
's key:
const getValueOrFalse = (name: string) => {
if (isObjKey(name, lookup)) {
// name narrowed to "foo" | "bar"
return lookup[name]
}
return false
}
function isObjKey<T>(key: PropertyKey, obj: T): key is keyof T {
return key in obj;
}
Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With