I have an object a that only contains a subset of the keys defined in type B. I then have a variable d of type B. I want to extract the value for key d from a in case it exists there.
const a = {x: 'c'}
type B = 'x' | 'y'
const example = (d: B) => {
let e: string
if (d in a) e = a[d]
}
But Typescript will complain with error 7027 on a[d]:
Element implicitly has an 'any' type because expression of type 'B' can't be used to index type '{ x: string; }'.
Property 'y' does not exist on type '{ x: string; }'
It seems that the compiler is blind to the check d in a.
Why? And what’s the best way to solve this?
innarrowing: typescriptlang.org/docs/handbook/2/….disn't a string literal andadoesn't have a union type.inoperatorkey in objonly narrows the type ofobj, and only ifkeyis of a single string literal type, and only ifobjis of a union type. Since yourkeyis a union and yourobjis not, theinoperator will not do any narrowing. Even ms/TS#21732, if implemented, would probably not do what you want, since all that would possibly do is narrowafrom{x: string}to{x: string} | {y: unknown}.if (d === "x"). If you have a list of keys then you might want a type guard to narrowdto an element in the list like this approach. It's technically unsound to assume(d in a)implies thatdis one of the known keys ofa, see this.ato bePartial<Record<...>>and then instead of using anintype guard (which doesn't work how you want) you just reada[d]and check it. Let me know if you want to see any of this written up as an answer.