This is ultimately a design limitation of TypeScript. It does not use type guards on an object’s properties to narrow the object itself, except in the particular case where the object is a discriminated union type… and in your case, A
isn’t a union at all, let alone a discriminated one.
The way I’d do this for your case is to introduce a user-defined type guard function which explicitly performs the narrowing you expect: you pass in an object with a key
property, and return true
or false
depending on whether or not this object is a valid B
:
const isB = (x: { key: any }): x is B => typeof x.key === "string";
Then you use it:
if (isB(a)) {
func(a); // okay
}
This is (give or take a function call) essentially the same logic as your code, but the compiler recognizes your intent now. Okay, hope that helps; good luck!