diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1edbb1d4a0dd3..778d5e2dfa736 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22691,7 +22691,7 @@ namespace ts { const keyPropertyName = getKeyPropertyName(unionType); const propNode = keyPropertyName && find(node.properties, p => p.symbol && p.kind === SyntaxKind.PropertyAssignment && p.symbol.escapedName === keyPropertyName && isPossiblyDiscriminantValue(p.initializer)); - const propType = propNode && getTypeOfExpression((propNode as PropertyAssignment).initializer); + const propType = propNode && getContextFreeTypeOfExpression((propNode as PropertyAssignment).initializer); return propType && getConstituentTypeForKeyType(unionType, propType); } @@ -26198,7 +26198,7 @@ namespace ts { concatenate( map( filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.JsxAttribute && isDiscriminantProperty(contextualType, p.symbol.escapedName) && (!p.initializer || isPossiblyDiscriminantValue(p.initializer))), - prop => ([!(prop as JsxAttribute).initializer ? (() => trueType) : (() => checkExpression((prop as JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => Type, __String]) + prop => ([!(prop as JsxAttribute).initializer ? (() => trueType) : (() => getContextFreeTypeOfExpression((prop as JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => Type, __String]) ), map( filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), diff --git a/tests/baselines/reference/discriminatedUnionJsxElement.js b/tests/baselines/reference/discriminatedUnionJsxElement.js new file mode 100644 index 0000000000000..ca5b766aac92f --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionJsxElement.js @@ -0,0 +1,57 @@ +//// [discriminatedUnionJsxElement.tsx] +// Repro from #46021 + +interface IData { + menuItemsVariant?: MenuItemVariant; +} + +function Menu(data: IData) { + const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine; + return ; +} + +type IListItemData = { variant: ListItemVariant.Avatar; } | { variant: ListItemVariant.OneLine; }; + +enum ListItemVariant { + OneLine, + Avatar, +} + +function ListItem(_data: IListItemData) { + return null; +} + + +//// [discriminatedUnionJsxElement.jsx] +"use strict"; +// Repro from #46021 +function Menu(data) { + var _a; + var listItemVariant = (_a = data.menuItemsVariant) !== null && _a !== void 0 ? _a : ListItemVariant.OneLine; + return ; +} +var ListItemVariant; +(function (ListItemVariant) { + ListItemVariant[ListItemVariant["OneLine"] = 0] = "OneLine"; + ListItemVariant[ListItemVariant["Avatar"] = 1] = "Avatar"; +})(ListItemVariant || (ListItemVariant = {})); +function ListItem(_data) { + return null; +} + + +//// [discriminatedUnionJsxElement.d.ts] +interface IData { + menuItemsVariant?: MenuItemVariant; +} +declare function Menu(data: IData): any; +declare type IListItemData = { + variant: ListItemVariant.Avatar; +} | { + variant: ListItemVariant.OneLine; +}; +declare enum ListItemVariant { + OneLine = 0, + Avatar = 1 +} +declare function ListItem(_data: IListItemData): null; diff --git a/tests/baselines/reference/discriminatedUnionJsxElement.symbols b/tests/baselines/reference/discriminatedUnionJsxElement.symbols new file mode 100644 index 0000000000000..aa884f5a1b0a8 --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionJsxElement.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/discriminatedUnionJsxElement.tsx === +// Repro from #46021 + +interface IData { +>IData : Symbol(IData, Decl(discriminatedUnionJsxElement.tsx, 0, 0)) +>MenuItemVariant : Symbol(MenuItemVariant, Decl(discriminatedUnionJsxElement.tsx, 2, 16)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) + + menuItemsVariant?: MenuItemVariant; +>menuItemsVariant : Symbol(IData.menuItemsVariant, Decl(discriminatedUnionJsxElement.tsx, 2, 84)) +>MenuItemVariant : Symbol(MenuItemVariant, Decl(discriminatedUnionJsxElement.tsx, 2, 16)) +} + +function Menu(data: IData) { +>Menu : Symbol(Menu, Decl(discriminatedUnionJsxElement.tsx, 4, 1)) +>MenuItemVariant : Symbol(MenuItemVariant, Decl(discriminatedUnionJsxElement.tsx, 6, 14)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) +>data : Symbol(data, Decl(discriminatedUnionJsxElement.tsx, 6, 81)) +>IData : Symbol(IData, Decl(discriminatedUnionJsxElement.tsx, 0, 0)) +>MenuItemVariant : Symbol(MenuItemVariant, Decl(discriminatedUnionJsxElement.tsx, 6, 14)) + + const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine; +>listItemVariant : Symbol(listItemVariant, Decl(discriminatedUnionJsxElement.tsx, 7, 9)) +>data.menuItemsVariant : Symbol(IData.menuItemsVariant, Decl(discriminatedUnionJsxElement.tsx, 2, 84)) +>data : Symbol(data, Decl(discriminatedUnionJsxElement.tsx, 6, 81)) +>menuItemsVariant : Symbol(IData.menuItemsVariant, Decl(discriminatedUnionJsxElement.tsx, 2, 84)) +>ListItemVariant.OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) + + return ; +>ListItem : Symbol(ListItem, Decl(discriminatedUnionJsxElement.tsx, 16, 1)) +>variant : Symbol(variant, Decl(discriminatedUnionJsxElement.tsx, 8, 20)) +>listItemVariant : Symbol(listItemVariant, Decl(discriminatedUnionJsxElement.tsx, 7, 9)) +} + +type IListItemData = { variant: ListItemVariant.Avatar; } | { variant: ListItemVariant.OneLine; }; +>IListItemData : Symbol(IListItemData, Decl(discriminatedUnionJsxElement.tsx, 9, 1)) +>variant : Symbol(variant, Decl(discriminatedUnionJsxElement.tsx, 11, 22)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>Avatar : Symbol(ListItemVariant.Avatar, Decl(discriminatedUnionJsxElement.tsx, 14, 12)) +>variant : Symbol(variant, Decl(discriminatedUnionJsxElement.tsx, 11, 61)) +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) +>OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) + +enum ListItemVariant { +>ListItemVariant : Symbol(ListItemVariant, Decl(discriminatedUnionJsxElement.tsx, 11, 98)) + + OneLine, +>OneLine : Symbol(ListItemVariant.OneLine, Decl(discriminatedUnionJsxElement.tsx, 13, 22)) + + Avatar, +>Avatar : Symbol(ListItemVariant.Avatar, Decl(discriminatedUnionJsxElement.tsx, 14, 12)) +} + +function ListItem(_data: IListItemData) { +>ListItem : Symbol(ListItem, Decl(discriminatedUnionJsxElement.tsx, 16, 1)) +>_data : Symbol(_data, Decl(discriminatedUnionJsxElement.tsx, 18, 18)) +>IListItemData : Symbol(IListItemData, Decl(discriminatedUnionJsxElement.tsx, 9, 1)) + + return null; +} + diff --git a/tests/baselines/reference/discriminatedUnionJsxElement.types b/tests/baselines/reference/discriminatedUnionJsxElement.types new file mode 100644 index 0000000000000..54ca2b4268f54 --- /dev/null +++ b/tests/baselines/reference/discriminatedUnionJsxElement.types @@ -0,0 +1,57 @@ +=== tests/cases/compiler/discriminatedUnionJsxElement.tsx === +// Repro from #46021 + +interface IData { +>ListItemVariant : any + + menuItemsVariant?: MenuItemVariant; +>menuItemsVariant : MenuItemVariant | undefined +} + +function Menu(data: IData) { +>Menu : (data: IData) => any +>ListItemVariant : any +>data : IData + + const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine; +>listItemVariant : ListItemVariant.OneLine | NonNullable +>data.menuItemsVariant ?? ListItemVariant.OneLine : ListItemVariant.OneLine | NonNullable +>data.menuItemsVariant : MenuItemVariant | undefined +>data : IData +>menuItemsVariant : MenuItemVariant | undefined +>ListItemVariant.OneLine : ListItemVariant.OneLine +>ListItemVariant : typeof ListItemVariant +>OneLine : ListItemVariant.OneLine + + return ; +> : error +>ListItem : (_data: IListItemData) => null +>variant : ListItemVariant +>listItemVariant : ListItemVariant +} + +type IListItemData = { variant: ListItemVariant.Avatar; } | { variant: ListItemVariant.OneLine; }; +>IListItemData : IListItemData +>variant : ListItemVariant.Avatar +>ListItemVariant : any +>variant : ListItemVariant.OneLine +>ListItemVariant : any + +enum ListItemVariant { +>ListItemVariant : ListItemVariant + + OneLine, +>OneLine : ListItemVariant.OneLine + + Avatar, +>Avatar : ListItemVariant.Avatar +} + +function ListItem(_data: IListItemData) { +>ListItem : (_data: IListItemData) => null +>_data : IListItemData + + return null; +>null : null +} + diff --git a/tests/cases/compiler/discriminatedUnionJsxElement.tsx b/tests/cases/compiler/discriminatedUnionJsxElement.tsx new file mode 100644 index 0000000000000..b000c2fb2a032 --- /dev/null +++ b/tests/cases/compiler/discriminatedUnionJsxElement.tsx @@ -0,0 +1,25 @@ +// @strict: true +// @declaration: true +// @jsx: preserve + +// Repro from #46021 + +interface IData { + menuItemsVariant?: MenuItemVariant; +} + +function Menu(data: IData) { + const listItemVariant = data.menuItemsVariant ?? ListItemVariant.OneLine; + return ; +} + +type IListItemData = { variant: ListItemVariant.Avatar; } | { variant: ListItemVariant.OneLine; }; + +enum ListItemVariant { + OneLine, + Avatar, +} + +function ListItem(_data: IListItemData) { + return null; +}