Description
Bug Report
Please feel free to change the title to make it more accurate. I wasn't sure what to call this
π Search Terms
union narrow
π Version & Regression Information
5.1.6
β― Playground Link
Playground link with relevant code
π» Code
export type DomNodeStyle = ElementStyle | ImageStyle;
export type ElementStyle = {
tagName: string;
style: { key: string; value: string }[];
children: (ElementStyle | ContentStyle)[];
};
export type ContentStyle = { content: string };
export type ImageStyle = {
tagName: 'img';
imageSource: string | null;
style: { key: string; value: string }[];
children: (ElementStyle | ContentStyle)[];
};
const image = {
tagName: 'img',
imageSource: 'https://example.com/image.jpg', // This is correct. Compiler requires `imageSource` because tagName is `img`.
style: [],
children: []
};
function doSomeWork(node: DomNodeStyle) {
if (image.tagName === "img") { // Narrowing is not occurring correctly
console.log(image.imageSource) // Error message: Property 'imageSource' does not exist on type 'ElementStyle'
}
}
π Actual behavior
For a partially discriminated union, when trying to access a narrowed field value, the compiler does not properly narrow the type. This forces the user to use the in
operator to determine if the field exists. When instantiating the object though, the compiler does correctly infer that the field from the narrowed type needs to exist.
π Expected behavior
I would expect the compiler to properly narrow the type if the explicitly defined union is set. In this case, if tagName
is img
, the compiler should infer that imageSource
is required and available. If tagName
is any other string value, the compiler should fall back to ElementStyle
for the type.