From f218b978b7cf8286e495179104a1017f45d314c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 19 Aug 2024 12:25:17 +0200 Subject: [PATCH] handle filtering mapped types as types that might exclude properties --- src/compiler/checker.ts | 2 +- ...LikeConstraintInGenericMappedType3.symbols | 129 +++++++++++++++++ ...peLikeConstraintInGenericMappedType3.types | 135 ++++++++++++++++++ ...dTypeLikeConstraintInGenericMappedType3.ts | 49 +++++++ 4 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.symbols create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.types create mode 100644 tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fc515dffbc47..321e12c4d2a5e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31744,7 +31744,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); const constraint = getConstraintTypeFromMappedType(type); // special case for conditional types pretending to be negated types - if (isExcludedMappedPropertyName(constraint, propertyNameType)) { + if (type.nameType && isExcludedMappedPropertyName(type.nameType, propertyNameType) || isExcludedMappedPropertyName(constraint, propertyNameType)) { return; } const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.symbols b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.symbols new file mode 100644 index 0000000000000..ba631da07b54d --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.symbols @@ -0,0 +1,129 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts === +type MappedOmit = { [P in keyof T as Exclude]: T[P]; } +>MappedOmit : Symbol(MappedOmit, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 0)) +>T : Symbol(T, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 16)) +>K : Symbol(K, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 18)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 45)) +>T : Symbol(T, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 16)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 45)) +>K : Symbol(K, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 18)) +>T : Symbol(T, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 16)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 45)) + +type IntrinsicElements = { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 84)) + + div: { +>div : Symbol(div, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 2, 26)) + + onChange: (ev: Event) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 3, 8)) +>ev : Symbol(ev, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 4, 15)) +>Event : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + }; + span: { +>span : Symbol(span, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 5, 4)) + + onChange: (ev: Event) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 6, 9)) +>ev : Symbol(ev, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 7, 15)) +>Event : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + }; +}; + +type ElementType = keyof IntrinsicElements; +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 9, 2)) +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 84)) + +let DEFAULT_TABS_TAG = "div" as const; +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 13, 3)) +>const : Symbol(const) + +type Props = MappedOmit< +>Props : Symbol(Props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 13, 38)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 15, 11)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 9, 2)) +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 15, 36)) +>MappedOmit : Symbol(MappedOmit, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 0)) + + IntrinsicElements[TTag], +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 0, 84)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 15, 11)) + + keyof Overrides +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 15, 36)) + +> & + Overrides; +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 15, 36)) + +type TabGroupProps = Props< +>TabGroupProps : Symbol(TabGroupProps, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 19, 12)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 21, 19)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 9, 2)) +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 13, 3)) +>Props : Symbol(Props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 13, 38)) + + TTag, +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 21, 19)) + { + defaultIndex?: number; +>defaultIndex : Symbol(defaultIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 23, 3)) + + onChange?: (index: number) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 24, 26)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 25, 16)) + + selectedIndex?: number; +>selectedIndex : Symbol(selectedIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 25, 39)) + + vertical?: boolean; +>vertical : Symbol(vertical, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 26, 27)) + + manual?: boolean; +>manual : Symbol(manual, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 27, 23)) + } +>; + +interface _internal_ComponentTabGroup { +>_internal_ComponentTabGroup : Symbol(_internal_ComponentTabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 30, 2)) + + ( +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 33, 3)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 9, 2)) +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 13, 3)) + + props: TabGroupProps, +>props : Symbol(props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 33, 55)) +>TabGroupProps : Symbol(TabGroupProps, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 19, 12)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 33, 3)) + + ): null; +} + +declare let TabGroup: _internal_ComponentTabGroup; +>TabGroup : Symbol(TabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 38, 11)) +>_internal_ComponentTabGroup : Symbol(_internal_ComponentTabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 30, 2)) + +TabGroup({ +>TabGroup : Symbol(TabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 38, 11)) + + defaultIndex: 0, +>defaultIndex : Symbol(defaultIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 40, 10)) + + onChange: (index) => { +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 41, 18)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 42, 13)) + + const i: number = index; +>i : Symbol(i, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 43, 9)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts, 42, 13)) + + }, +}); + diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.types b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.types new file mode 100644 index 0000000000000..b397cc9ae29cd --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.types @@ -0,0 +1,135 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts === +type MappedOmit = { [P in keyof T as Exclude]: T[P]; } +>MappedOmit : MappedOmit +> : ^^^^^^^^^^^^^^^^ + +type IntrinsicElements = { +>IntrinsicElements : IntrinsicElements +> : ^^^^^^^^^^^^^^^^^ + + div: { +>div : { onChange: (ev: Event) => void; } +> : ^^^^^^^^^^^^ ^^^ + + onChange: (ev: Event) => void; +>onChange : (ev: Event) => void +> : ^ ^^ ^^^^^ +>ev : Event +> : ^^^^^ + + }; + span: { +>span : { onChange: (ev: Event) => void; } +> : ^^^^^^^^^^^^ ^^^ + + onChange: (ev: Event) => void; +>onChange : (ev: Event) => void +> : ^ ^^ ^^^^^ +>ev : Event +> : ^^^^^ + + }; +}; + +type ElementType = keyof IntrinsicElements; +>ElementType : keyof IntrinsicElements +> : ^^^^^^^^^^^^^^^^^^^^^^^ + +let DEFAULT_TABS_TAG = "div" as const; +>DEFAULT_TABS_TAG : "div" +> : ^^^^^ +>"div" as const : "div" +> : ^^^^^ +>"div" : "div" +> : ^^^^^ + +type Props = MappedOmit< +>Props : Props +> : ^^^^^^^^^^^^^^^^^^^^^^ + + IntrinsicElements[TTag], + keyof Overrides +> & + Overrides; + +type TabGroupProps = Props< +>TabGroupProps : TabGroupProps +> : ^^^^^^^^^^^^^^^^^^^ +>DEFAULT_TABS_TAG : "div" +> : ^^^^^ + + TTag, + { + defaultIndex?: number; +>defaultIndex : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + + onChange?: (index: number) => void; +>onChange : ((index: number) => void) | undefined +> : ^^ ^^ ^^^^^ ^^^^^^^^^^^^^ +>index : number +> : ^^^^^^ + + selectedIndex?: number; +>selectedIndex : number | undefined +> : ^^^^^^^^^^^^^^^^^^ + + vertical?: boolean; +>vertical : boolean | undefined +> : ^^^^^^^^^^^^^^^^^^^ + + manual?: boolean; +>manual : boolean | undefined +> : ^^^^^^^^^^^^^^^^^^^ + } +>; + +interface _internal_ComponentTabGroup { + ( +>DEFAULT_TABS_TAG : "div" +> : ^^^^^ + + props: TabGroupProps, +>props : TabGroupProps +> : ^^^^^^^^^^^^^^^^^^^ + + ): null; +} + +declare let TabGroup: _internal_ComponentTabGroup; +>TabGroup : _internal_ComponentTabGroup +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TabGroup({ +>TabGroup({ defaultIndex: 0, onChange: (index) => { const i: number = index; },}) : null +> : ^^^^ +>TabGroup : _internal_ComponentTabGroup +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ defaultIndex: 0, onChange: (index) => { const i: number = index; },} : { defaultIndex: number; onChange: (index: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + defaultIndex: 0, +>defaultIndex : number +> : ^^^^^^ +>0 : 0 +> : ^ + + onChange: (index) => { +>onChange : (index: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(index) => { const i: number = index; } : (index: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>index : number +> : ^^^^^^ + + const i: number = index; +>i : number +> : ^^^^^^ +>index : number +> : ^^^^^^ + + }, +}); + diff --git a/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts new file mode 100644 index 0000000000000..3eb0fa4e4db33 --- /dev/null +++ b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType3.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noEmit: true + +type MappedOmit = { [P in keyof T as Exclude]: T[P]; } + +type IntrinsicElements = { + div: { + onChange: (ev: Event) => void; + }; + span: { + onChange: (ev: Event) => void; + }; +}; + +type ElementType = keyof IntrinsicElements; + +let DEFAULT_TABS_TAG = "div" as const; + +type Props = MappedOmit< + IntrinsicElements[TTag], + keyof Overrides +> & + Overrides; + +type TabGroupProps = Props< + TTag, + { + defaultIndex?: number; + onChange?: (index: number) => void; + selectedIndex?: number; + vertical?: boolean; + manual?: boolean; + } +>; + +interface _internal_ComponentTabGroup { + ( + props: TabGroupProps, + ): null; +} + +declare let TabGroup: _internal_ComponentTabGroup; + +TabGroup({ + defaultIndex: 0, + onChange: (index) => { + const i: number = index; + }, +});