Consider this code:
const obj = {
a: 1,
b: 2
}
let possibleKey: string = 'a'
if (possibleKey in obj) console.log(obj[possibleKey])
When possibleKey in obj
is true, we know that possibleKey
has type keyof typeof obj
, right? Why doesn't TypeScript type system detects that and narrows down string
to that type? Instead, it says:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ a: number; b: number; }'.
keyof is a keyword in TypeScript which is used to extract the key type from an object type.
TypeScript follows possible paths of execution that our programs can take to analyze the most specific possible type of a value at a given position. It looks at these special checks (called type guards) and assignments, and the process of refining types to more specific types than declared is called narrowing.
In Typescript, we have three ways to work with it using: typeof: the keyword helps to check values types, like boolean, string, number, etc. instanceof: the keyword to compare the object instance with a class constructor. type guards: The powerful way to check types using typescript feature language.
Per the docs:
For a
n in x
expression, wheren
is a string literal or string literal type andx
is a union type, the “true” branch narrows to types which have an optional or required propertyn
, and the “false” branch narrows to types which have an optional or missing propertyn
.
In other words, n in x
narrows x
, not n
, and only for string literals or string literal types in
union types. For that expression to work, you'd have to give the compiler more information, e.g. using a type assertion:
if (possibleKey in obj) {
console.log(obj[<keyof typeof obj>possibleKey]);
}
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