1

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?

5
  • 1
    Note the limitations of in narrowing: typescriptlang.org/docs/handbook/2/…. d isn't a string literal and a doesn't have a union type. Commented Feb 15, 2022 at 16:50
  • Not a duplicate, but this other Q&A should answer the part about what to do instead. Commented Feb 15, 2022 at 16:54
  • The in operator key in obj only narrows the type of obj, and only if key is of a single string literal type, and only if obj is of a union type. Since your key is a union and your obj is not, the in operator 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 narrow a from {x: string} to {x: string} | {y: unknown}. Commented Feb 15, 2022 at 16:58
  • What's the primary question, here? Is it "why is this happening?" Or is it "how do I work around it"? If it's "why", then I can explain that by expanding on the above. If it's "how", then it depends on your use case. The example you posted would be better solved by if (d === "x"). If you have a list of keys then you might want a type guard to narrow d to an element in the list like this approach. It's technically unsound to assume (d in a) implies that d is one of the known keys of a, see this. Commented Feb 15, 2022 at 17:06
  • Another approach is this one where you are explicitly defining a to be Partial<Record<...>> and then instead of using an in type guard (which doesn't work how you want) you just read a[d] and check it. Let me know if you want to see any of this written up as an answer. Commented Feb 15, 2022 at 17:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.