From f6074e850dd4ffc444b1ae9d3118b6604a6100fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 2 Jan 2023 22:33:09 +0100 Subject: [PATCH 01/23] Revert "Revert "Fixed an issue with contextual type for intersection properties (#48668)" (#50279)" This reverts commit adf26ffa4b00bda9b35b048b4f1083836451463e. --- src/compiler/checker.ts | 32 +++++++- ...lTypeFunctionObjectPropertyIntersection.js | 42 ++++++++++ ...FunctionObjectPropertyIntersection.symbols | 82 +++++++++++++++++++ ...peFunctionObjectPropertyIntersection.types | 73 +++++++++++++++++ ...lTypeFunctionObjectPropertyIntersection.ts | 29 +++++++ 5 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js create mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols create mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types create mode 100644 tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 54ddbb48fe11a..fe77c1891f878 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28416,6 +28416,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { + if (t.flags & TypeFlags.Intersection) { + const intersection = t as IntersectionType; + let newTypes = mapDefined(intersection.types, getTypeOfConcretePropertyOfContextualType); + if (newTypes.length > 0) { + return getIntersectionType(newTypes); + } + newTypes = mapDefined(intersection.types, getTypeOfApplicableIndexInfoOfContextualType); + if (newTypes.length > 0) { + return getIntersectionType(newTypes); + } + return undefined; + } + const concretePropertyType = getTypeOfConcretePropertyOfContextualType(t); + if (concretePropertyType) { + return concretePropertyType; + } + return getTypeOfApplicableIndexInfoOfContextualType(t); + }, /*noReductions*/ true); + + function getTypeOfConcretePropertyOfContextualType(t: Type) { if (isGenericMappedType(t) && !t.declaration.nameType) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; @@ -28423,8 +28443,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { return substituteIndexedMappedType(t, propertyNameType); } + return undefined; } - else if (t.flags & TypeFlags.StructuredType) { + if (t.flags & TypeFlags.StructuredType) { const prop = getPropertyOfType(t, name); if (prop) { return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop); @@ -28435,10 +28456,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return restType; } } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } return undefined; - }, /*noReductions*/ true); + } + function getTypeOfApplicableIndexInfoOfContextualType(t: Type) { + if (!(t.flags & TypeFlags.StructuredType)) { + return undefined; + } + return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; + } } // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js new file mode 100644 index 0000000000000..f1dab3794105a --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js @@ -0,0 +1,42 @@ +//// [contextualTypeFunctionObjectPropertyIntersection.ts] +type Action = (ev: TEvent) => void; + +interface MachineConfig { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"]]?: Action; + } & { + "*"?: Action; + }; +} + +declare function createMachine( + config: MachineConfig +): void; + +createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: (ev) => { + ev.type; // should be 'FOO' + }, + }, +}); + + +//// [contextualTypeFunctionObjectPropertyIntersection.js] +"use strict"; +createMachine({ + schema: { + events: {}, + }, + on: { + FOO: function (ev) { + ev.type; // should be 'FOO' + }, + }, +}); diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols new file mode 100644 index 0000000000000..4690985350a17 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -0,0 +1,82 @@ +=== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts === +type Action = (ev: TEvent) => void; +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 12)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 28)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 48)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 12)) + +interface MachineConfig { +>MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 68)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 40)) + + schema: { +>schema : Symbol(MachineConfig.schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 58)) + + events: TEvent; +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 3, 11)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) + + }; + on?: { +>on : Symbol(MachineConfig.on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 5, 4)) + + [K in TEvent["type"]]?: Action; +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 51)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) + + } & { + "*"?: Action; +>"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 8, 7)) +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) + + }; +} + +declare function createMachine( +>createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 11, 1)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 31)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 47)) + + config: MachineConfig +>config : Symbol(config, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 64)) +>MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 68)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 31)) + +): void; + +createMachine({ +>createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 11, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 17, 15)) + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 18, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 37)) + + }, + on: { +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 20, 4)) + + FOO: (ev) => { +>FOO : Symbol(FOO, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 22, 10)) + + ev.type; // should be 'FOO' +>ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 22, 10)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) + + }, + }, +}); + diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types new file mode 100644 index 0000000000000..30ba52626faa5 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -0,0 +1,73 @@ +=== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts === +type Action = (ev: TEvent) => void; +>Action : Action +>type : string +>ev : TEvent + +interface MachineConfig { +>type : string + + schema: { +>schema : { events: TEvent; } + + events: TEvent; +>events : TEvent + + }; + on?: { +>on : ({ [K in TEvent["type"]]?: Action | undefined; } & { "*"?: Action | undefined; }) | undefined + + [K in TEvent["type"]]?: Action; +>type : K + + } & { + "*"?: Action; +>"*" : Action | undefined + + }; +} + +declare function createMachine( +>createMachine : (config: MachineConfig) => void +>type : string + + config: MachineConfig +>config : MachineConfig + +): void; + +createMachine({ +>createMachine({ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { FOO: (ev) => { ev.type; // should be 'FOO' }, },}) : void +>createMachine : (config: MachineConfig) => void +>{ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { FOO: (ev) => { ev.type; // should be 'FOO' }, },} : { schema: { events: { type: "FOO"; } | { type: "BAR"; }; }; on: { FOO: (ev: { type: "FOO"; }) => void; }; } + + schema: { +>schema : { events: { type: "FOO"; } | { type: "BAR"; }; } +>{ events: {} as { type: "FOO" } | { type: "BAR" }, } : { events: { type: "FOO"; } | { type: "BAR"; }; } + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : { type: "FOO"; } | { type: "BAR"; } +>{} as { type: "FOO" } | { type: "BAR" } : { type: "FOO"; } | { type: "BAR"; } +>{} : {} +>type : "FOO" +>type : "BAR" + + }, + on: { +>on : { FOO: (ev: { type: "FOO"; }) => void; } +>{ FOO: (ev) => { ev.type; // should be 'FOO' }, } : { FOO: (ev: { type: "FOO"; }) => void; } + + FOO: (ev) => { +>FOO : (ev: { type: "FOO"; }) => void +>(ev) => { ev.type; // should be 'FOO' } : (ev: { type: "FOO"; }) => void +>ev : { type: "FOO"; } + + ev.type; // should be 'FOO' +>ev.type : "FOO" +>ev : { type: "FOO"; } +>type : "FOO" + + }, + }, +}); + diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts new file mode 100644 index 0000000000000..2d7e00f32f65e --- /dev/null +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -0,0 +1,29 @@ +// @strict: true + +type Action = (ev: TEvent) => void; + +interface MachineConfig { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"]]?: Action; + } & { + "*"?: Action; + }; +} + +declare function createMachine( + config: MachineConfig +): void; + +createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: (ev) => { + ev.type; // should be 'FOO' + }, + }, +}); From 5b9a5ddf78698b24f2c405cf00f2c3790248f7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 2 Jan 2023 22:47:52 +0100 Subject: [PATCH 02/23] Add failing test cases related to RTK --- ...ctionObjectPropertyIntersection.errors.txt | 99 ++++++++ ...lTypeFunctionObjectPropertyIntersection.js | 42 ---- ...FunctionObjectPropertyIntersection.symbols | 234 +++++++++++++++--- ...peFunctionObjectPropertyIntersection.types | 136 ++++++++++ ...lTypeFunctionObjectPropertyIntersection.ts | 60 +++++ 5 files changed, 493 insertions(+), 78 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt delete mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt new file mode 100644 index 0000000000000..6c3b8432ab05b --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt @@ -0,0 +1,99 @@ +tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(40,5): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(49,8): error TS7006: Parameter 's' implicitly has an 'any' type. +tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(84,25): error TS7006: Parameter 'state' implicitly has an 'any' type. + + +==== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts (3 errors) ==== + // repro from #48812 + + type Action = (ev: TEvent) => void; + + interface MachineConfig { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"]]?: Action; + } & { + "*"?: Action; + }; + } + + declare function createMachine( + config: MachineConfig + ): void; + + createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: (ev) => { + ev.type; // should be 'FOO' + }, + }, + }); + + // repro from #49307#issuecomment-1143103607 + + declare function createSlice( + reducers: { [K: string]: (state: string) => void } & { + [K in keyof T]: object; + } + ): void; + + createSlice({ + f(a) {}, // implicit any, index signature should not be used here + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + }); + + // repro from #49307#issuecomment-1196014488 + + type Validate = T & { [K in keyof T]: object } + declare function f any>>(s: S, x: Validate): void; + + f(0, { + foo: s => s + 1, + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + }) + + // repro from 49307#issuecomment-1195858950 + + type SliceCaseReducers = { + [K: string]: (state: State) => State | void; + }; + + type ValidateSliceCaseReducers> = ACR & { + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any; + } + ? { + prepare(...a: never[]): Omit; + } + : {}; + }; + + declare function createSlice< + State, + CaseReducers extends SliceCaseReducers + >(options: { + initialState: State | (() => State); + reducers: ValidateSliceCaseReducers; + }): void; + + export const clientSlice = createSlice({ + initialState: { + username: "", + isLoggedIn: false, + userId: "", + avatar: "", + }, + reducers: { + onClientUserChanged(state) {}, + ~~~~~ +!!! error TS7006: Parameter 'state' implicitly has an 'any' type. + }, + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js deleted file mode 100644 index f1dab3794105a..0000000000000 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.js +++ /dev/null @@ -1,42 +0,0 @@ -//// [contextualTypeFunctionObjectPropertyIntersection.ts] -type Action = (ev: TEvent) => void; - -interface MachineConfig { - schema: { - events: TEvent; - }; - on?: { - [K in TEvent["type"]]?: Action; - } & { - "*"?: Action; - }; -} - -declare function createMachine( - config: MachineConfig -): void; - -createMachine({ - schema: { - events: {} as { type: "FOO" } | { type: "BAR" }, - }, - on: { - FOO: (ev) => { - ev.type; // should be 'FOO' - }, - }, -}); - - -//// [contextualTypeFunctionObjectPropertyIntersection.js] -"use strict"; -createMachine({ - schema: { - events: {}, - }, - on: { - FOO: function (ev) { - ev.type; // should be 'FOO' - }, - }, -}); diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols index 4690985350a17..c7313ce595796 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -1,82 +1,244 @@ === tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts === +// repro from #48812 + type Action = (ev: TEvent) => void; >Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 12)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 28)) ->ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 48)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 12)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 12)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 28)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 48)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 12)) interface MachineConfig { ->MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 68)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 40)) +>MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 68)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 40)) schema: { ->schema : Symbol(MachineConfig.schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 58)) +>schema : Symbol(MachineConfig.schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 58)) events: TEvent; ->events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 3, 11)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 5, 11)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) }; on?: { ->on : Symbol(MachineConfig.on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 5, 4)) +>on : Symbol(MachineConfig.on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 4)) [K in TEvent["type"]]?: Action; ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 5)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 9, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) >Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 51)) ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 5)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 9, 51)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 9, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) } & { "*"?: Action; ->"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 8, 7)) +>"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 10, 7)) >Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 24)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) }; } declare function createMachine( ->createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 11, 1)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 31)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 47)) +>createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 1)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 15, 31)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 15, 47)) config: MachineConfig ->config : Symbol(config, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 64)) ->MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 68)) ->TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 31)) +>config : Symbol(config, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 15, 64)) +>MachineConfig : Symbol(MachineConfig, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 2, 68)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 15, 31)) ): void; createMachine({ ->createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 11, 1)) +>createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 1)) schema: { ->schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 17, 15)) +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 15)) events: {} as { type: "FOO" } | { type: "BAR" }, ->events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 18, 11)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 37)) +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 20, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 37)) }, on: { ->on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 20, 4)) +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 22, 4)) FOO: (ev) => { ->FOO : Symbol(FOO, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 7)) ->ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 22, 10)) +>FOO : Symbol(FOO, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 23, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 24, 10)) ev.type; // should be 'FOO' ->ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) ->ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 22, 10)) ->type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 19)) +>ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 19)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 24, 10)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 21, 19)) }, }, }); +// repro from #49307#issuecomment-1143103607 + +declare function createSlice( +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 29)) + + reducers: { [K: string]: (state: string) => void } & { +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 32)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 33, 15)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 33, 28)) + + [K in keyof T]: object; +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 34, 5)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 29)) + } +): void; + +createSlice({ +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) + + f(a) {}, // implicit any, index signature should not be used here +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 38, 13)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 4)) + +}); + +// repro from #49307#issuecomment-1196014488 + +type Validate = T & { [K in keyof T]: object } +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 40, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 26)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) + +declare function f any>>(s: S, x: Validate): void; +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 49)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 21)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 48)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 67)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) +>x : Symbol(x, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 72)) +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 40, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 21)) + +f(0, { +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 49)) + + foo: s => s + 1, +>foo : Symbol(foo, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 47, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 48, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 48, 6)) + +}) + +// repro from 49307#issuecomment-1195858950 + +type SliceCaseReducers = { +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) + + [K: string]: (state: State) => State | void; +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 54, 3)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 54, 16)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) + +}; + +type ValidateSliceCaseReducers> = ACR & { +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 2)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) + + [T in keyof ACR]: ACR[T] extends { +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 3)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 3)) + + reducer(s: S, action?: infer A): any; +>reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 36)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 12)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) +>action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 17)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 32)) + } + ? { + prepare(...a: never[]): Omit; +>prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 61, 7)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 62, 16)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 32)) + } + : {}; +}; + +declare function createSlice< +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) + + State, +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) + + CaseReducers extends SliceCaseReducers +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 8)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) + +>(options: { +>options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 2)) + + initialState: State | (() => State); +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 12)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) + + reducers: ValidateSliceCaseReducers; +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 71, 38)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 8)) + +}): void; + +export const clientSlice = createSlice({ +>clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 12)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) + + initialState: { +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 40)) + + username: "", +>username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 17)) + + isLoggedIn: false, +>isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 17)) + + userId: "", +>userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 78, 22)) + + avatar: "", +>avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 15)) + + }, + reducers: { +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 81, 4)) + + onClientUserChanged(state) {}, +>onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 82, 13)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 83, 24)) + + }, +}); + diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types index 30ba52626faa5..d263c7a92cf1c 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -1,4 +1,6 @@ === tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts === +// repro from #48812 + type Action = (ev: TEvent) => void; >Action : Action >type : string @@ -71,3 +73,137 @@ createMachine({ }, }); +// repro from #49307#issuecomment-1143103607 + +declare function createSlice( +>createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } + + reducers: { [K: string]: (state: string) => void } & { +>reducers : { [K: string]: (state: string) => void; } & { [K in keyof T]: object; } +>K : string +>state : string + + [K in keyof T]: object; + } +): void; + +createSlice({ +>createSlice({ f(a) {}, // implicit any, index signature should not be used here}) : void +>createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } +>{ f(a) {}, // implicit any, index signature should not be used here} : { f(a: any): void; } + + f(a) {}, // implicit any, index signature should not be used here +>f : (a: any) => void +>a : any + +}); + +// repro from #49307#issuecomment-1196014488 + +type Validate = T & { [K in keyof T]: object } +>Validate : Validate + +declare function f any>>(s: S, x: Validate): void; +>f : any>>(s: S, x: Validate) => void +>state : S +>s : S +>x : Validate + +f(0, { +>f(0, { foo: s => s + 1,}) : void +>f : any>>(s: S, x: Validate) => void +>0 : 0 +>{ foo: s => s + 1,} : { foo: (s: any) => any; } + + foo: s => s + 1, +>foo : (s: any) => any +>s => s + 1 : (s: any) => any +>s : any +>s + 1 : any +>s : any +>1 : 1 + +}) + +// repro from 49307#issuecomment-1195858950 + +type SliceCaseReducers = { +>SliceCaseReducers : SliceCaseReducers + + [K: string]: (state: State) => State | void; +>K : string +>state : State + +}; + +type ValidateSliceCaseReducers> = ACR & { +>ValidateSliceCaseReducers : ValidateSliceCaseReducers + + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any; +>reducer : (s: S, action?: infer A) => any +>s : S +>action : A | undefined + } + ? { + prepare(...a: never[]): Omit; +>prepare : (...a: never[]) => Omit +>a : never[] + } + : {}; +}; + +declare function createSlice< +>createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers;}): void; } + + State, + CaseReducers extends SliceCaseReducers +>(options: { +>options : { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; } + + initialState: State | (() => State); +>initialState : State | (() => State) + + reducers: ValidateSliceCaseReducers; +>reducers : ValidateSliceCaseReducers + +}): void; + +export const clientSlice = createSlice({ +>clientSlice : void +>createSlice({ initialState: { username: "", isLoggedIn: false, userId: "", avatar: "", }, reducers: { onClientUserChanged(state) {}, },}) : void +>createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } +>{ initialState: { username: "", isLoggedIn: false, userId: "", avatar: "", }, reducers: { onClientUserChanged(state) {}, },} : { initialState: { username: string; isLoggedIn: false; userId: string; avatar: string; }; reducers: { onClientUserChanged(state: any): void; }; } + + initialState: { +>initialState : { username: string; isLoggedIn: false; userId: string; avatar: string; } +>{ username: "", isLoggedIn: false, userId: "", avatar: "", } : { username: string; isLoggedIn: false; userId: string; avatar: string; } + + username: "", +>username : string +>"" : "" + + isLoggedIn: false, +>isLoggedIn : false +>false : false + + userId: "", +>userId : string +>"" : "" + + avatar: "", +>avatar : string +>"" : "" + + }, + reducers: { +>reducers : { onClientUserChanged(state: any): void; } +>{ onClientUserChanged(state) {}, } : { onClientUserChanged(state: any): void; } + + onClientUserChanged(state) {}, +>onClientUserChanged : (state: any) => void +>state : any + + }, +}); + diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts index 2d7e00f32f65e..f3d13812f4cfa 100644 --- a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -1,4 +1,7 @@ // @strict: true +// @noEmit: true + +// repro from #48812 type Action = (ev: TEvent) => void; @@ -27,3 +30,60 @@ createMachine({ }, }, }); + +// repro from #49307#issuecomment-1143103607 + +declare function createSlice( + reducers: { [K: string]: (state: string) => void } & { + [K in keyof T]: object; + } +): void; + +createSlice({ + f(a) {}, // implicit any, index signature should not be used here +}); + +// repro from #49307#issuecomment-1196014488 + +type Validate = T & { [K in keyof T]: object } +declare function f any>>(s: S, x: Validate): void; + +f(0, { + foo: s => s + 1, +}) + +// repro from 49307#issuecomment-1195858950 + +type SliceCaseReducers = { + [K: string]: (state: State) => State | void; +}; + +type ValidateSliceCaseReducers> = ACR & { + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any; + } + ? { + prepare(...a: never[]): Omit; + } + : {}; +}; + +declare function createSlice< + State, + CaseReducers extends SliceCaseReducers +>(options: { + initialState: State | (() => State); + reducers: ValidateSliceCaseReducers; +}): void; + +export const clientSlice = createSlice({ + initialState: { + username: "", + isLoggedIn: false, + userId: "", + avatar: "", + }, + reducers: { + onClientUserChanged(state) {}, + }, +}); From bafe4fbe48eeced8c4e13f8ef7fa483772e0e331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 4 Jan 2023 07:15:50 +0100 Subject: [PATCH 03/23] Treat properties of non-generic mapped types as concrete-like --- src/compiler/checker.ts | 9 +- ...ctionObjectPropertyIntersection.errors.txt | 12 +-- ...FunctionObjectPropertyIntersection.symbols | 92 +++++++++---------- ...peFunctionObjectPropertyIntersection.types | 29 +++--- ...lTypeFunctionObjectPropertyIntersection.ts | 4 +- 5 files changed, 65 insertions(+), 81 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fe77c1891f878..014676cdfe9db 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28418,7 +28418,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return mapType(type, t => { if (t.flags & TypeFlags.Intersection) { const intersection = t as IntersectionType; - let newTypes = mapDefined(intersection.types, getTypeOfConcretePropertyOfContextualType); + let newTypes = mapDefined(intersection.types, getTypeOfConcreteLikePropertyOfContextualType); if (newTypes.length > 0) { return getIntersectionType(newTypes); } @@ -28428,14 +28428,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return undefined; } - const concretePropertyType = getTypeOfConcretePropertyOfContextualType(t); + const concretePropertyType = getTypeOfConcreteLikePropertyOfContextualType(t); if (concretePropertyType) { return concretePropertyType; } return getTypeOfApplicableIndexInfoOfContextualType(t); }, /*noReductions*/ true); - function getTypeOfConcretePropertyOfContextualType(t: Type) { + function getTypeOfConcreteLikePropertyOfContextualType(t: Type) { if (isGenericMappedType(t) && !t.declaration.nameType) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; @@ -28456,6 +28456,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return restType; } } + if (getObjectFlags(t) & ObjectFlags.Mapped) { + return getTypeOfApplicableIndexInfoOfContextualType(t); + } } return undefined; } diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt index 6c3b8432ab05b..5c317f2374a20 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt @@ -1,9 +1,7 @@ tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(40,5): error TS7006: Parameter 'a' implicitly has an 'any' type. -tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(49,8): error TS7006: Parameter 's' implicitly has an 'any' type. -tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(84,25): error TS7006: Parameter 'state' implicitly has an 'any' type. -==== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts (3 errors) ==== +==== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts (1 errors) ==== // repro from #48812 type Action = (ev: TEvent) => void; @@ -55,15 +53,11 @@ tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(84,25): f(0, { foo: s => s + 1, - ~ -!!! error TS7006: Parameter 's' implicitly has an 'any' type. }) // repro from 49307#issuecomment-1195858950 - type SliceCaseReducers = { - [K: string]: (state: State) => State | void; - }; + type SliceCaseReducers = Record State | void>; type ValidateSliceCaseReducers> = ACR & { [T in keyof ACR]: ACR[T] extends { @@ -92,8 +86,6 @@ tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(84,25): }, reducers: { onClientUserChanged(state) {}, - ~~~~~ -!!! error TS7006: Parameter 'state' implicitly has an 'any' type. }, }); \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols index c7313ce595796..1593f5dbbeb14 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -85,7 +85,7 @@ createMachine({ // repro from #49307#issuecomment-1143103607 declare function createSlice( ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) >T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 29)) reducers: { [K: string]: (state: string) => void } & { @@ -100,7 +100,7 @@ declare function createSlice( ): void; createSlice({ ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) f(a) {}, // implicit any, index signature should not be used here >f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 38, 13)) @@ -142,102 +142,98 @@ f(0, { // repro from 49307#issuecomment-1195858950 -type SliceCaseReducers = { +type SliceCaseReducers = Record State | void>; >SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) >State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) - - [K: string]: (state: State) => State | void; ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 54, 3)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 54, 16)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 48)) >State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) >State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) -}; - type ValidateSliceCaseReducers> = ACR & { ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 2)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 79)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) >SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) [T in keyof ACR]: ACR[T] extends { ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 3)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 33)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 3)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 3)) reducer(s: S, action?: infer A): any; ->reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 36)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 12)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 31)) ->action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 17)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 32)) +>reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 36)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 12)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) +>action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 17)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 32)) } ? { prepare(...a: never[]): Omit; ->prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 61, 7)) ->a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 62, 16)) +>prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 7)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 16)) >Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 32)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 32)) } : {}; }; declare function createSlice< ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) State, ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) CaseReducers extends SliceCaseReducers ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 8)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 8)) >SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) >(options: { ->options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 2)) +>options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 2)) initialState: State | (() => State); ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 12)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 12)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) reducers: ValidateSliceCaseReducers; ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 71, 38)) ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 29)) ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 8)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 38)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 79)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 8)) }): void; export const clientSlice = createSlice({ ->clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 12)) ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 2)) +>clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 73, 12)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) initialState: { ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 40)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 73, 40)) username: "", ->username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 17)) +>username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 17)) isLoggedIn: false, ->isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 17)) +>isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 17)) userId: "", ->userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 78, 22)) +>userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 22)) avatar: "", ->avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 15)) +>avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 15)) }, reducers: { ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 81, 4)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 4)) onClientUserChanged(state) {}, ->onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 82, 13)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 83, 24)) +>onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 13)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 81, 24)) }, }); diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types index d263c7a92cf1c..16e98a0e87f8b 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -113,29 +113,24 @@ f(0, { >f(0, { foo: s => s + 1,}) : void >f : any>>(s: S, x: Validate) => void >0 : 0 ->{ foo: s => s + 1,} : { foo: (s: any) => any; } +>{ foo: s => s + 1,} : { foo: (s: number) => number; } foo: s => s + 1, ->foo : (s: any) => any ->s => s + 1 : (s: any) => any ->s : any ->s + 1 : any ->s : any +>foo : (s: number) => number +>s => s + 1 : (s: number) => number +>s : number +>s + 1 : number +>s : number >1 : 1 }) // repro from 49307#issuecomment-1195858950 -type SliceCaseReducers = { +type SliceCaseReducers = Record State | void>; >SliceCaseReducers : SliceCaseReducers - - [K: string]: (state: State) => State | void; ->K : string >state : State -}; - type ValidateSliceCaseReducers> = ACR & { >ValidateSliceCaseReducers : ValidateSliceCaseReducers @@ -173,7 +168,7 @@ export const clientSlice = createSlice({ >clientSlice : void >createSlice({ initialState: { username: "", isLoggedIn: false, userId: "", avatar: "", }, reducers: { onClientUserChanged(state) {}, },}) : void >createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } ->{ initialState: { username: "", isLoggedIn: false, userId: "", avatar: "", }, reducers: { onClientUserChanged(state) {}, },} : { initialState: { username: string; isLoggedIn: false; userId: string; avatar: string; }; reducers: { onClientUserChanged(state: any): void; }; } +>{ initialState: { username: "", isLoggedIn: false, userId: "", avatar: "", }, reducers: { onClientUserChanged(state) {}, },} : { initialState: { username: string; isLoggedIn: false; userId: string; avatar: string; }; reducers: { onClientUserChanged(state: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }): void; }; } initialState: { >initialState : { username: string; isLoggedIn: false; userId: string; avatar: string; } @@ -197,12 +192,12 @@ export const clientSlice = createSlice({ }, reducers: { ->reducers : { onClientUserChanged(state: any): void; } ->{ onClientUserChanged(state) {}, } : { onClientUserChanged(state: any): void; } +>reducers : { onClientUserChanged(state: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }): void; } +>{ onClientUserChanged(state) {}, } : { onClientUserChanged(state: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }): void; } onClientUserChanged(state) {}, ->onClientUserChanged : (state: any) => void ->state : any +>onClientUserChanged : (state: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }) => void +>state : { username: string; isLoggedIn: boolean; userId: string; avatar: string; } }, }); diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts index f3d13812f4cfa..2cbd09e7251e2 100644 --- a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -54,9 +54,7 @@ f(0, { // repro from 49307#issuecomment-1195858950 -type SliceCaseReducers = { - [K: string]: (state: State) => State | void; -}; +type SliceCaseReducers = Record State | void>; type ValidateSliceCaseReducers> = ACR & { [T in keyof ACR]: ACR[T] extends { From 3ab57738eb32fe8715fbbd14bccbf1e96e5ddf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 22 May 2023 21:39:05 +0200 Subject: [PATCH 04/23] always concat indexed mapped type substitutions with either types from concrete props or from applicable index infos --- src/compiler/checker.ts | 81 ++++++++++------- ...ctionObjectPropertyIntersection.errors.txt | 91 ------------------- ...FunctionObjectPropertyIntersection.symbols | 2 +- ...peFunctionObjectPropertyIntersection.types | 10 +- ...lTypeFunctionObjectPropertyIntersection.ts | 2 +- 5 files changed, 53 insertions(+), 133 deletions(-) delete mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1dd558dc15125..0af6b57ace8cd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29148,54 +29148,65 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return mapType(type, t => { if (t.flags & TypeFlags.Intersection) { const intersection = t as IntersectionType; - let newTypes = mapDefined(intersection.types, getTypeOfConcreteLikePropertyOfContextualType); - if (newTypes.length > 0) { - return getIntersectionType(newTypes); + let applicableIndexedMappedTypeSubstitions: Type[] | undefined; + let concreteProperties: Type[] | undefined; + let applicableIndexInfoCandidates: Type[] | undefined; + for (const t of intersection.types) { + if (isGenericMappedType(t) && !t.declaration.nameType) { + applicableIndexedMappedTypeSubstitions = append(applicableIndexedMappedTypeSubstitions, getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t)); + continue; + } + if (!(t.flags & TypeFlags.StructuredType)) { + continue; + } + let type: Type | undefined; + if (type = getTypeOfConcretePropertyOfContextualType(t)) { + concreteProperties = append(concreteProperties, type); + continue; + } + applicableIndexInfoCandidates = append(applicableIndexInfoCandidates, t); + } + if (concreteProperties) { + return getIntersectionType(concatenate(concreteProperties, applicableIndexedMappedTypeSubstitions)); } - newTypes = mapDefined(intersection.types, getTypeOfApplicableIndexInfoOfContextualType); - if (newTypes.length > 0) { - return getIntersectionType(newTypes); + const types = concatenate(mapDefined(applicableIndexInfoCandidates, getTypeOfApplicableIndexInfoOfContextualType), applicableIndexedMappedTypeSubstitions); + if (types.length > 0) { + return getIntersectionType(types); } return undefined; } - const concretePropertyType = getTypeOfConcreteLikePropertyOfContextualType(t); - if (concretePropertyType) { - return concretePropertyType; + if (isGenericMappedType(t) && !t.declaration.nameType) { + return getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t); + } + if (!(t.flags & TypeFlags.StructuredType)) { + return undefined; } - return getTypeOfApplicableIndexInfoOfContextualType(t); + return getTypeOfConcretePropertyOfContextualType(t) || getTypeOfApplicableIndexInfoOfContextualType(t); }, /*noReductions*/ true); - function getTypeOfConcreteLikePropertyOfContextualType(t: Type) { - if (isGenericMappedType(t) && !t.declaration.nameType) { - const constraint = getConstraintTypeFromMappedType(t); - const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); - if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { - return substituteIndexedMappedType(t, propertyNameType); - } - return undefined; + function getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t: MappedType) { + const constraint = getConstraintTypeFromMappedType(t); + const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); + if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { + return substituteIndexedMappedType(t, propertyNameType); } - if (t.flags & TypeFlags.StructuredType) { - const prop = getPropertyOfType(t, name); - if (prop) { - return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop); - } - if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { - const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); - if (restType) { - return restType; - } - } - if (getObjectFlags(t) & ObjectFlags.Mapped) { - return getTypeOfApplicableIndexInfoOfContextualType(t); + return undefined; + } + function getTypeOfConcretePropertyOfContextualType(t: Type) { + const prop = getPropertyOfType(t, name); + if (prop) { + return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop); + } + if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { + const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); + if (restType) { + return restType; } } return undefined; } function getTypeOfApplicableIndexInfoOfContextualType(t: Type) { - if (!(t.flags & TypeFlags.StructuredType)) { - return undefined; - } return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } } diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt deleted file mode 100644 index 5c317f2374a20..0000000000000 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt +++ /dev/null @@ -1,91 +0,0 @@ -tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts(40,5): error TS7006: Parameter 'a' implicitly has an 'any' type. - - -==== tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts (1 errors) ==== - // repro from #48812 - - type Action = (ev: TEvent) => void; - - interface MachineConfig { - schema: { - events: TEvent; - }; - on?: { - [K in TEvent["type"]]?: Action; - } & { - "*"?: Action; - }; - } - - declare function createMachine( - config: MachineConfig - ): void; - - createMachine({ - schema: { - events: {} as { type: "FOO" } | { type: "BAR" }, - }, - on: { - FOO: (ev) => { - ev.type; // should be 'FOO' - }, - }, - }); - - // repro from #49307#issuecomment-1143103607 - - declare function createSlice( - reducers: { [K: string]: (state: string) => void } & { - [K in keyof T]: object; - } - ): void; - - createSlice({ - f(a) {}, // implicit any, index signature should not be used here - ~ -!!! error TS7006: Parameter 'a' implicitly has an 'any' type. - }); - - // repro from #49307#issuecomment-1196014488 - - type Validate = T & { [K in keyof T]: object } - declare function f any>>(s: S, x: Validate): void; - - f(0, { - foo: s => s + 1, - }) - - // repro from 49307#issuecomment-1195858950 - - type SliceCaseReducers = Record State | void>; - - type ValidateSliceCaseReducers> = ACR & { - [T in keyof ACR]: ACR[T] extends { - reducer(s: S, action?: infer A): any; - } - ? { - prepare(...a: never[]): Omit; - } - : {}; - }; - - declare function createSlice< - State, - CaseReducers extends SliceCaseReducers - >(options: { - initialState: State | (() => State); - reducers: ValidateSliceCaseReducers; - }): void; - - export const clientSlice = createSlice({ - initialState: { - username: "", - isLoggedIn: false, - userId: "", - avatar: "", - }, - reducers: { - onClientUserChanged(state) {}, - }, - }); - \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols index 1593f5dbbeb14..4cc58ac4f6b15 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -102,7 +102,7 @@ declare function createSlice( createSlice({ >createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) - f(a) {}, // implicit any, index signature should not be used here + f(a) {}, >f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 38, 13)) >a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 4)) diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types index 16e98a0e87f8b..bee2a4b146c8d 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -88,13 +88,13 @@ declare function createSlice( ): void; createSlice({ ->createSlice({ f(a) {}, // implicit any, index signature should not be used here}) : void +>createSlice({ f(a) {},}) : void >createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } ->{ f(a) {}, // implicit any, index signature should not be used here} : { f(a: any): void; } +>{ f(a) {},} : { f(a: string): void; } - f(a) {}, // implicit any, index signature should not be used here ->f : (a: any) => void ->a : any + f(a) {}, +>f : (a: string) => void +>a : string }); diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts index 2cbd09e7251e2..db09170d13e95 100644 --- a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -40,7 +40,7 @@ declare function createSlice( ): void; createSlice({ - f(a) {}, // implicit any, index signature should not be used here + f(a) {}, }); // repro from #49307#issuecomment-1196014488 From 48faaa32a667eabd52232271fdb0f285df9cd318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 23 May 2023 00:35:36 +0200 Subject: [PATCH 05/23] tweak code --- src/compiler/checker.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0af6b57ace8cd..7cfcd2b5682d4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29146,6 +29146,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { + if (!(t.flags & TypeFlags.StructuredType)) { + return undefined; + } if (t.flags & TypeFlags.Intersection) { const intersection = t as IntersectionType; let applicableIndexedMappedTypeSubstitions: Type[] | undefined; @@ -29156,12 +29159,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { applicableIndexedMappedTypeSubstitions = append(applicableIndexedMappedTypeSubstitions, getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t)); continue; } - if (!(t.flags & TypeFlags.StructuredType)) { - continue; - } - let type: Type | undefined; - if (type = getTypeOfConcretePropertyOfContextualType(t)) { - concreteProperties = append(concreteProperties, type); + const typeOfConcreteProperty = getTypeOfConcretePropertyOfContextualType(t); + if (typeOfConcreteProperty) { + concreteProperties = append(concreteProperties, typeOfConcreteProperty); continue; } applicableIndexInfoCandidates = append(applicableIndexInfoCandidates, t); @@ -29175,13 +29175,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return undefined; } - if (isGenericMappedType(t) && !t.declaration.nameType) { - return getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t); - } - if (!(t.flags & TypeFlags.StructuredType)) { - return undefined; - } - return getTypeOfConcretePropertyOfContextualType(t) || getTypeOfApplicableIndexInfoOfContextualType(t); + return isGenericMappedType(t) && !t.declaration.nameType + ? getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t) + : getTypeOfConcretePropertyOfContextualType(t) || getTypeOfApplicableIndexInfoOfContextualType(t); }, /*noReductions*/ true); function getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t: MappedType) { From 937a0ea6d37fccecd267b256942cb0f36cddeb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 23 May 2023 00:38:53 +0200 Subject: [PATCH 06/23] rename variable --- src/compiler/checker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7cfcd2b5682d4..9386544d0bcf4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29152,7 +29152,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (t.flags & TypeFlags.Intersection) { const intersection = t as IntersectionType; let applicableIndexedMappedTypeSubstitions: Type[] | undefined; - let concreteProperties: Type[] | undefined; + let concretePropertyTypes: Type[] | undefined; let applicableIndexInfoCandidates: Type[] | undefined; for (const t of intersection.types) { if (isGenericMappedType(t) && !t.declaration.nameType) { @@ -29161,13 +29161,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const typeOfConcreteProperty = getTypeOfConcretePropertyOfContextualType(t); if (typeOfConcreteProperty) { - concreteProperties = append(concreteProperties, typeOfConcreteProperty); + concretePropertyTypes = append(concretePropertyTypes, typeOfConcreteProperty); continue; } applicableIndexInfoCandidates = append(applicableIndexInfoCandidates, t); } - if (concreteProperties) { - return getIntersectionType(concatenate(concreteProperties, applicableIndexedMappedTypeSubstitions)); + if (concretePropertyTypes) { + return getIntersectionType(concatenate(concretePropertyTypes, applicableIndexedMappedTypeSubstitions)); } const types = concatenate(mapDefined(applicableIndexInfoCandidates, getTypeOfApplicableIndexInfoOfContextualType), applicableIndexedMappedTypeSubstitions); if (types.length > 0) { From 6d24ca825d1726d0b07d3e99e7bf0fbee394e1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 25 Jul 2023 18:34:33 +0200 Subject: [PATCH 07/23] Add an extra test case related to JSX --- .../contextuallyTypedJsxAttribute2.symbols | 48 +++++++++++++++++++ .../contextuallyTypedJsxAttribute2.types | 44 +++++++++++++++++ .../contextuallyTypedJsxAttribute2.tsx | 20 ++++++++ 3 files changed, 112 insertions(+) create mode 100644 tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols create mode 100644 tests/baselines/reference/contextuallyTypedJsxAttribute2.types create mode 100644 tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx diff --git a/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols new file mode 100644 index 0000000000000..f8fb7991cb23b --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols @@ -0,0 +1,48 @@ +//// [tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx] //// + +=== contextuallyTypedJsxAttribute2.tsx === +/// + +import React from "react"; +>React : Symbol(React, Decl(contextuallyTypedJsxAttribute2.tsx, 2, 6)) + +import { ComponentPropsWithRef, ElementType } from "react"; +>ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 8)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) + +function UnwrappedLink( +>UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) + + props: Omit, "as"> & { +>props : Symbol(props, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 60)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 8)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) + + as?: T; +>as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 6, 79)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) + + }, +) { + return ; +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +} + + {}} />; +>UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 14)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 25)) + + {}} />; +>UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) +>as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 14)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 26)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 37)) + diff --git a/tests/baselines/reference/contextuallyTypedJsxAttribute2.types b/tests/baselines/reference/contextuallyTypedJsxAttribute2.types new file mode 100644 index 0000000000000..05a6356dd284f --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.types @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx] //// + +=== contextuallyTypedJsxAttribute2.tsx === +/// + +import React from "react"; +>React : typeof React + +import { ComponentPropsWithRef, ElementType } from "react"; +>ComponentPropsWithRef : any +>ElementType : any + +function UnwrappedLink( +>UnwrappedLink : (props: Omit, "as"> & { as?: T;}) => JSX.Element + + props: Omit, "as"> & { +>props : Omit, "as"> & { as?: T | undefined; } + + as?: T; +>as : T | undefined + + }, +) { + return ; +> : JSX.Element +>a : any +>a : any +} + + {}} />; +> {}} /> : JSX.Element +>UnwrappedLink : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element +>onClick : (e: React.MouseEvent) => void +>(e) => {} : (e: React.MouseEvent) => void +>e : React.MouseEvent + + {}} />; +> {}} /> : JSX.Element +>UnwrappedLink : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element +>as : "button" +>onClick : (e: React.MouseEvent) => void +>(e) => {} : (e: React.MouseEvent) => void +>e : React.MouseEvent + diff --git a/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx new file mode 100644 index 0000000000000..d94409f720ce0 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx @@ -0,0 +1,20 @@ +// @strict: true +// @jsx: react +// @esModuleInterop: true +// @noEmit: true + +/// + +import React from "react"; +import { ComponentPropsWithRef, ElementType } from "react"; + +function UnwrappedLink( + props: Omit, "as"> & { + as?: T; + }, +) { + return ; +} + + {}} />; + {}} />; From ea31c96a72f5c19b3d960b45dae3cdba83cbbb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 25 Jul 2023 18:46:57 +0200 Subject: [PATCH 08/23] expand the JSX test --- .../contextuallyTypedJsxAttribute2.symbols | 49 ++++++++++++++----- .../contextuallyTypedJsxAttribute2.types | 34 ++++++++++--- .../contextuallyTypedJsxAttribute2.tsx | 12 ++++- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols index f8fb7991cb23b..0d9415509ce8e 100644 --- a/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols @@ -16,7 +16,7 @@ function UnwrappedLink( >ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) >ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) - props: Omit, "as"> & { + props: Omit, "as">, >props : Symbol(props, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 60)) >Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) >ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 8)) @@ -24,9 +24,34 @@ function UnwrappedLink( >T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) >T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) +) { + return ; +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +} + + {}} />; +>UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 14)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 25)) + +function UnwrappedLink2( +>UnwrappedLink2 : Symbol(UnwrappedLink2, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 38)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 24)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) + + props: Omit, "as"> & { +>props : Symbol(props, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 61)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 8)) +>ElementType : Symbol(ElementType, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 31)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 24)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 24)) + as?: T; ->as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 6, 79)) ->T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 5, 23)) +>as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 79)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 24)) }, ) { @@ -35,14 +60,14 @@ function UnwrappedLink( >a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) } - {}} />; ->UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) ->onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 14)) ->e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 25)) + {}} />; +>UnwrappedLink2 : Symbol(UnwrappedLink2, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 38)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 21, 15)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 21, 26)) - {}} />; ->UnwrappedLink : Symbol(UnwrappedLink, Decl(contextuallyTypedJsxAttribute2.tsx, 3, 59)) ->as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 14)) ->onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 26)) ->e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 14, 37)) + {}} />; +>UnwrappedLink2 : Symbol(UnwrappedLink2, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 38)) +>as : Symbol(as, Decl(contextuallyTypedJsxAttribute2.tsx, 22, 15)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 22, 27)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 22, 38)) diff --git a/tests/baselines/reference/contextuallyTypedJsxAttribute2.types b/tests/baselines/reference/contextuallyTypedJsxAttribute2.types index 05a6356dd284f..5fb6754f96150 100644 --- a/tests/baselines/reference/contextuallyTypedJsxAttribute2.types +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.types @@ -11,7 +11,27 @@ import { ComponentPropsWithRef, ElementType } from "react"; >ElementType : any function UnwrappedLink( ->UnwrappedLink : (props: Omit, "as"> & { as?: T;}) => JSX.Element +>UnwrappedLink : (props: Omit, "as">) => JSX.Element + + props: Omit, "as">, +>props : Omit, "as"> + +) { + return ; +> : JSX.Element +>a : any +>a : any +} + + {}} />; +> {}} /> : JSX.Element +>UnwrappedLink : (props: Omit, "as">) => JSX.Element +>onClick : (e: React.MouseEvent) => void +>(e) => {} : (e: React.MouseEvent) => void +>e : React.MouseEvent + +function UnwrappedLink2( +>UnwrappedLink2 : (props: Omit, "as"> & { as?: T;}) => JSX.Element props: Omit, "as"> & { >props : Omit, "as"> & { as?: T | undefined; } @@ -27,16 +47,16 @@ function UnwrappedLink( >a : any } - {}} />; -> {}} /> : JSX.Element ->UnwrappedLink : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element + {}} />; +> {}} /> : JSX.Element +>UnwrappedLink2 : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element >onClick : (e: React.MouseEvent) => void >(e) => {} : (e: React.MouseEvent) => void >e : React.MouseEvent - {}} />; -> {}} /> : JSX.Element ->UnwrappedLink : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element + {}} />; +> {}} /> : JSX.Element +>UnwrappedLink2 : (props: Omit, "as"> & { as?: T | undefined; }) => JSX.Element >as : "button" >onClick : (e: React.MouseEvent) => void >(e) => {} : (e: React.MouseEvent) => void diff --git a/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx index d94409f720ce0..003a44b6d8287 100644 --- a/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx +++ b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx @@ -9,6 +9,14 @@ import React from "react"; import { ComponentPropsWithRef, ElementType } from "react"; function UnwrappedLink( + props: Omit, "as">, +) { + return ; +} + + {}} />; + +function UnwrappedLink2( props: Omit, "as"> & { as?: T; }, @@ -16,5 +24,5 @@ function UnwrappedLink( return ; } - {}} />; - {}} />; + {}} />; + {}} />; From 1f9c4ea28ae2166045e1b62e4e7c2876019f1102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 30 Jul 2024 03:10:51 +0200 Subject: [PATCH 09/23] add test case for intersected reverse mapped types --- ...everseMappedIntersectionInference1.symbols | 121 ++++++++++++++ .../reverseMappedIntersectionInference1.types | 151 ++++++++++++++++++ .../reverseMappedIntersectionInference1.ts | 43 +++++ 3 files changed, 315 insertions(+) create mode 100644 tests/baselines/reference/reverseMappedIntersectionInference1.symbols create mode 100644 tests/baselines/reference/reverseMappedIntersectionInference1.types create mode 100644 tests/cases/compiler/reverseMappedIntersectionInference1.ts diff --git a/tests/baselines/reference/reverseMappedIntersectionInference1.symbols b/tests/baselines/reference/reverseMappedIntersectionInference1.symbols new file mode 100644 index 0000000000000..93bf0ed99c21c --- /dev/null +++ b/tests/baselines/reference/reverseMappedIntersectionInference1.symbols @@ -0,0 +1,121 @@ +//// [tests/cases/compiler/reverseMappedIntersectionInference1.ts] //// + +=== reverseMappedIntersectionInference1.ts === +type Results = { +>Results : Symbol(Results, Decl(reverseMappedIntersectionInference1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 0, 13)) + + [K in keyof T]: { +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 1, 3)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 0, 13)) + + data: T[K]; +>data : Symbol(data, Decl(reverseMappedIntersectionInference1.ts, 1, 19)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 0, 13)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 1, 3)) + + onSuccess: (data: T[K]) => void; +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference1.ts, 2, 15)) +>data : Symbol(data, Decl(reverseMappedIntersectionInference1.ts, 3, 16)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 0, 13)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 1, 3)) + + }; +}; + +type Errors = { +>Errors : Symbol(Errors, Decl(reverseMappedIntersectionInference1.ts, 5, 2)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 7, 12)) + + [K in keyof E]: { +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 8, 3)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 7, 12)) + + error: E[K]; +>error : Symbol(error, Decl(reverseMappedIntersectionInference1.ts, 8, 19)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 7, 12)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 8, 3)) + + onError: (data: E[K]) => void; +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference1.ts, 9, 16)) +>data : Symbol(data, Decl(reverseMappedIntersectionInference1.ts, 10, 14)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 7, 12)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference1.ts, 8, 3)) + + }; +}; + +declare function withKeyedObj( +>withKeyedObj : Symbol(withKeyedObj, Decl(reverseMappedIntersectionInference1.ts, 12, 2)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 14, 30)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 14, 32)) + + arg: Results & Errors +>arg : Symbol(arg, Decl(reverseMappedIntersectionInference1.ts, 14, 36)) +>Results : Symbol(Results, Decl(reverseMappedIntersectionInference1.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 14, 30)) +>Errors : Symbol(Errors, Decl(reverseMappedIntersectionInference1.ts, 5, 2)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 14, 32)) + +): [T, E]; +>T : Symbol(T, Decl(reverseMappedIntersectionInference1.ts, 14, 30)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference1.ts, 14, 32)) + +const res = withKeyedObj({ +>res : Symbol(res, Decl(reverseMappedIntersectionInference1.ts, 18, 5)) +>withKeyedObj : Symbol(withKeyedObj, Decl(reverseMappedIntersectionInference1.ts, 12, 2)) + + a: { +>a : Symbol(a, Decl(reverseMappedIntersectionInference1.ts, 18, 26)) + + data: "foo", +>data : Symbol(data, Decl(reverseMappedIntersectionInference1.ts, 19, 6)) + + onSuccess: (dataArg) => { +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference1.ts, 20, 16)) +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference1.ts, 21, 16)) + + dataArg; +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference1.ts, 21, 16)) + + }, + error: 404, +>error : Symbol(error, Decl(reverseMappedIntersectionInference1.ts, 23, 6)) + + onError: (errorArg) => { +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference1.ts, 24, 15)) +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference1.ts, 25, 14)) + + errorArg; +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference1.ts, 25, 14)) + + }, + }, + b: { +>b : Symbol(b, Decl(reverseMappedIntersectionInference1.ts, 28, 4)) + + data: true, +>data : Symbol(data, Decl(reverseMappedIntersectionInference1.ts, 29, 6)) + + onSuccess: (dataArg) => { +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference1.ts, 30, 15)) +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference1.ts, 31, 16)) + + dataArg; +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference1.ts, 31, 16)) + + }, + error: 500, +>error : Symbol(error, Decl(reverseMappedIntersectionInference1.ts, 33, 6)) + + onError: (errorArg) => { +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference1.ts, 34, 15)) +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference1.ts, 35, 14)) + + errorArg; +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference1.ts, 35, 14)) + + }, + }, +}); + diff --git a/tests/baselines/reference/reverseMappedIntersectionInference1.types b/tests/baselines/reference/reverseMappedIntersectionInference1.types new file mode 100644 index 0000000000000..6e035116b03b3 --- /dev/null +++ b/tests/baselines/reference/reverseMappedIntersectionInference1.types @@ -0,0 +1,151 @@ +//// [tests/cases/compiler/reverseMappedIntersectionInference1.ts] //// + +=== reverseMappedIntersectionInference1.ts === +type Results = { +>Results : Results +> : ^^^^^^^^^^ + + [K in keyof T]: { + data: T[K]; +>data : T[K] +> : ^^^^ + + onSuccess: (data: T[K]) => void; +>onSuccess : (data: T[K]) => void +> : ^ ^^ ^^^^^ +>data : T[K] +> : ^^^^ + + }; +}; + +type Errors = { +>Errors : Errors +> : ^^^^^^^^^ + + [K in keyof E]: { + error: E[K]; +>error : E[K] +> : ^^^^ + + onError: (data: E[K]) => void; +>onError : (data: E[K]) => void +> : ^ ^^ ^^^^^ +>data : E[K] +> : ^^^^ + + }; +}; + +declare function withKeyedObj( +>withKeyedObj : (arg: Results & Errors) => [T, E] +> : ^ ^^ ^^ ^^ ^^^^^ + + arg: Results & Errors +>arg : Results & Errors +> : ^^^^^^^^^^^^^^^^^^^^^^ + +): [T, E]; + +const res = withKeyedObj({ +>res : [{ a: string; b: boolean; }, { a: number; b: number; }] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>withKeyedObj({ a: { data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, }, b: { data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, },}) : [{ a: string; b: boolean; }, { a: number; b: number; }] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>withKeyedObj : (arg: Results & Errors) => [T, E] +> : ^ ^^ ^^ ^^ ^^^^^ +>{ a: { data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, }, b: { data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, },} : { a: { data: string; onSuccess: (dataArg: string) => void; error: number; onError: (errorArg: number) => void; }; b: { data: true; onSuccess: (dataArg: boolean) => void; error: number; onError: (errorArg: number) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + + a: { +>a : { data: string; onSuccess: (dataArg: string) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, } : { data: string; onSuccess: (dataArg: string) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + data: "foo", +>data : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + onSuccess: (dataArg) => { +>onSuccess : (dataArg: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(dataArg) => { dataArg; } : (dataArg: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>dataArg : string +> : ^^^^^^ + + dataArg; +>dataArg : string +> : ^^^^^^ + + }, + error: 404, +>error : number +> : ^^^^^^ +>404 : 404 +> : ^^^ + + onError: (errorArg) => { +>onError : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(errorArg) => { errorArg; } : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>errorArg : number +> : ^^^^^^ + + errorArg; +>errorArg : number +> : ^^^^^^ + + }, + }, + b: { +>b : { data: true; onSuccess: (dataArg: boolean) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ +>{ data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, } : { data: true; onSuccess: (dataArg: boolean) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + data: true, +>data : true +> : ^^^^ +>true : true +> : ^^^^ + + onSuccess: (dataArg) => { +>onSuccess : (dataArg: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>(dataArg) => { dataArg; } : (dataArg: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>dataArg : boolean +> : ^^^^^^^ + + dataArg; +>dataArg : boolean +> : ^^^^^^^ + + }, + error: 500, +>error : number +> : ^^^^^^ +>500 : 500 +> : ^^^ + + onError: (errorArg) => { +>onError : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(errorArg) => { errorArg; } : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>errorArg : number +> : ^^^^^^ + + errorArg; +>errorArg : number +> : ^^^^^^ + + }, + }, +}); + diff --git a/tests/cases/compiler/reverseMappedIntersectionInference1.ts b/tests/cases/compiler/reverseMappedIntersectionInference1.ts new file mode 100644 index 0000000000000..27b6889eb7c54 --- /dev/null +++ b/tests/cases/compiler/reverseMappedIntersectionInference1.ts @@ -0,0 +1,43 @@ +// @strict: true +// @noEmit: true + +type Results = { + [K in keyof T]: { + data: T[K]; + onSuccess: (data: T[K]) => void; + }; +}; + +type Errors = { + [K in keyof E]: { + error: E[K]; + onError: (data: E[K]) => void; + }; +}; + +declare function withKeyedObj( + arg: Results & Errors +): [T, E]; + +const res = withKeyedObj({ + a: { + data: "foo", + onSuccess: (dataArg) => { + dataArg; + }, + error: 404, + onError: (errorArg) => { + errorArg; + }, + }, + b: { + data: true, + onSuccess: (dataArg) => { + dataArg; + }, + error: 500, + onError: (errorArg) => { + errorArg; + }, + }, +}); From 52effa593957dbbc1ef261368ca10dd916c499cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 30 Jul 2024 07:29:54 +0200 Subject: [PATCH 10/23] add an extra test case --- ...everseMappedIntersectionInference2.symbols | 118 ++++++++++++++ .../reverseMappedIntersectionInference2.types | 150 ++++++++++++++++++ .../reverseMappedIntersectionInference2.ts | 43 +++++ 3 files changed, 311 insertions(+) create mode 100644 tests/baselines/reference/reverseMappedIntersectionInference2.symbols create mode 100644 tests/baselines/reference/reverseMappedIntersectionInference2.types create mode 100644 tests/cases/compiler/reverseMappedIntersectionInference2.ts diff --git a/tests/baselines/reference/reverseMappedIntersectionInference2.symbols b/tests/baselines/reference/reverseMappedIntersectionInference2.symbols new file mode 100644 index 0000000000000..18e65a100da78 --- /dev/null +++ b/tests/baselines/reference/reverseMappedIntersectionInference2.symbols @@ -0,0 +1,118 @@ +//// [tests/cases/compiler/reverseMappedIntersectionInference2.ts] //// + +=== reverseMappedIntersectionInference2.ts === +type Results = { +>Results : Symbol(Results, Decl(reverseMappedIntersectionInference2.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 0, 13)) + + [K in keyof T]: { +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 1, 3)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 0, 13)) + + data: T[K]; +>data : Symbol(data, Decl(reverseMappedIntersectionInference2.ts, 1, 19)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 0, 13)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 1, 3)) + + onSuccess: (data: T[K]) => void; +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference2.ts, 2, 15)) +>data : Symbol(data, Decl(reverseMappedIntersectionInference2.ts, 3, 16)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 0, 13)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 1, 3)) + + }; +}; + +type Errors = { +>Errors : Symbol(Errors, Decl(reverseMappedIntersectionInference2.ts, 5, 2)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 7, 12)) + + [K in keyof E]: { +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 8, 3)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 7, 12)) + + error: E[K]; +>error : Symbol(error, Decl(reverseMappedIntersectionInference2.ts, 8, 19)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 7, 12)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 8, 3)) + + onError: (data: E[K]) => void; +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference2.ts, 9, 16)) +>data : Symbol(data, Decl(reverseMappedIntersectionInference2.ts, 10, 14)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 7, 12)) +>K : Symbol(K, Decl(reverseMappedIntersectionInference2.ts, 8, 3)) + + }; +}; + +declare function withTupleLike( +>withTupleLike : Symbol(withTupleLike, Decl(reverseMappedIntersectionInference2.ts, 12, 2)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 14, 31)) +>0 : Symbol(0, Decl(reverseMappedIntersectionInference2.ts, 14, 42)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 14, 56)) +>0 : Symbol(0, Decl(reverseMappedIntersectionInference2.ts, 14, 68)) + + arg: Results & Errors +>arg : Symbol(arg, Decl(reverseMappedIntersectionInference2.ts, 14, 83)) +>Results : Symbol(Results, Decl(reverseMappedIntersectionInference2.ts, 0, 0)) +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 14, 31)) +>Errors : Symbol(Errors, Decl(reverseMappedIntersectionInference2.ts, 5, 2)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 14, 56)) + +): [T, E]; +>T : Symbol(T, Decl(reverseMappedIntersectionInference2.ts, 14, 31)) +>E : Symbol(E, Decl(reverseMappedIntersectionInference2.ts, 14, 56)) + +const res = withTupleLike([ +>res : Symbol(res, Decl(reverseMappedIntersectionInference2.ts, 18, 5)) +>withTupleLike : Symbol(withTupleLike, Decl(reverseMappedIntersectionInference2.ts, 12, 2)) + { + data: "foo", +>data : Symbol(data, Decl(reverseMappedIntersectionInference2.ts, 19, 3)) + + onSuccess: (dataArg) => { +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference2.ts, 20, 16)) +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference2.ts, 21, 16)) + + dataArg; +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference2.ts, 21, 16)) + + }, + error: 404, +>error : Symbol(error, Decl(reverseMappedIntersectionInference2.ts, 23, 6)) + + onError: (errorArg) => { +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference2.ts, 24, 15)) +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference2.ts, 25, 14)) + + errorArg; +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference2.ts, 25, 14)) + + }, + }, + { + data: true, +>data : Symbol(data, Decl(reverseMappedIntersectionInference2.ts, 29, 3)) + + onSuccess: (dataArg) => { +>onSuccess : Symbol(onSuccess, Decl(reverseMappedIntersectionInference2.ts, 30, 15)) +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference2.ts, 31, 16)) + + dataArg; +>dataArg : Symbol(dataArg, Decl(reverseMappedIntersectionInference2.ts, 31, 16)) + + }, + error: 500, +>error : Symbol(error, Decl(reverseMappedIntersectionInference2.ts, 33, 6)) + + onError: (errorArg) => { +>onError : Symbol(onError, Decl(reverseMappedIntersectionInference2.ts, 34, 15)) +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference2.ts, 35, 14)) + + errorArg; +>errorArg : Symbol(errorArg, Decl(reverseMappedIntersectionInference2.ts, 35, 14)) + + }, + }, +]); + diff --git a/tests/baselines/reference/reverseMappedIntersectionInference2.types b/tests/baselines/reference/reverseMappedIntersectionInference2.types new file mode 100644 index 0000000000000..4f5aa9e4d7d8d --- /dev/null +++ b/tests/baselines/reference/reverseMappedIntersectionInference2.types @@ -0,0 +1,150 @@ +//// [tests/cases/compiler/reverseMappedIntersectionInference2.ts] //// + +=== reverseMappedIntersectionInference2.ts === +type Results = { +>Results : Results +> : ^^^^^^^^^^ + + [K in keyof T]: { + data: T[K]; +>data : T[K] +> : ^^^^ + + onSuccess: (data: T[K]) => void; +>onSuccess : (data: T[K]) => void +> : ^ ^^ ^^^^^ +>data : T[K] +> : ^^^^ + + }; +}; + +type Errors = { +>Errors : Errors +> : ^^^^^^^^^ + + [K in keyof E]: { + error: E[K]; +>error : E[K] +> : ^^^^ + + onError: (data: E[K]) => void; +>onError : (data: E[K]) => void +> : ^ ^^ ^^^^^ +>data : E[K] +> : ^^^^ + + }; +}; + +declare function withTupleLike( +>withTupleLike : (arg: Results & Errors) => [T, E] +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>0 : unknown +> : ^^^^^^^ +>0 : unknown +> : ^^^^^^^ + + arg: Results & Errors +>arg : Results & Errors +> : ^^^^^^^^^^^^^^^^^^^^^^ + +): [T, E]; + +const res = withTupleLike([ +>res : [[string, boolean], [number, number]] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>withTupleLike([ { data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, }, { data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, },]) : [[string, boolean], [number, number]] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>withTupleLike : (arg: Results & Errors) => [T, E] +> : ^ ^^^^^^^^^ ^^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>[ { data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, }, { data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, },] : [{ data: string; onSuccess: (dataArg: string) => void; error: number; onError: (errorArg: number) => void; }, { data: true; onSuccess: (dataArg: boolean) => void; error: number; onError: (errorArg: number) => void; }] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ + { +>{ data: "foo", onSuccess: (dataArg) => { dataArg; }, error: 404, onError: (errorArg) => { errorArg; }, } : { data: string; onSuccess: (dataArg: string) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + data: "foo", +>data : string +> : ^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + onSuccess: (dataArg) => { +>onSuccess : (dataArg: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(dataArg) => { dataArg; } : (dataArg: string) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>dataArg : string +> : ^^^^^^ + + dataArg; +>dataArg : string +> : ^^^^^^ + + }, + error: 404, +>error : number +> : ^^^^^^ +>404 : 404 +> : ^^^ + + onError: (errorArg) => { +>onError : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(errorArg) => { errorArg; } : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>errorArg : number +> : ^^^^^^ + + errorArg; +>errorArg : number +> : ^^^^^^ + + }, + }, + { +>{ data: true, onSuccess: (dataArg) => { dataArg; }, error: 500, onError: (errorArg) => { errorArg; }, } : { data: true; onSuccess: (dataArg: boolean) => void; error: number; onError: (errorArg: number) => void; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + data: true, +>data : true +> : ^^^^ +>true : true +> : ^^^^ + + onSuccess: (dataArg) => { +>onSuccess : (dataArg: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>(dataArg) => { dataArg; } : (dataArg: boolean) => void +> : ^ ^^^^^^^^^^^^^^^^^^ +>dataArg : boolean +> : ^^^^^^^ + + dataArg; +>dataArg : boolean +> : ^^^^^^^ + + }, + error: 500, +>error : number +> : ^^^^^^ +>500 : 500 +> : ^^^ + + onError: (errorArg) => { +>onError : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(errorArg) => { errorArg; } : (errorArg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>errorArg : number +> : ^^^^^^ + + errorArg; +>errorArg : number +> : ^^^^^^ + + }, + }, +]); + diff --git a/tests/cases/compiler/reverseMappedIntersectionInference2.ts b/tests/cases/compiler/reverseMappedIntersectionInference2.ts new file mode 100644 index 0000000000000..107050d26acbe --- /dev/null +++ b/tests/cases/compiler/reverseMappedIntersectionInference2.ts @@ -0,0 +1,43 @@ +// @strict: true +// @noEmit: true + +type Results = { + [K in keyof T]: { + data: T[K]; + onSuccess: (data: T[K]) => void; + }; +}; + +type Errors = { + [K in keyof E]: { + error: E[K]; + onError: (data: E[K]) => void; + }; +}; + +declare function withTupleLike( + arg: Results & Errors +): [T, E]; + +const res = withTupleLike([ + { + data: "foo", + onSuccess: (dataArg) => { + dataArg; + }, + error: 404, + onError: (errorArg) => { + errorArg; + }, + }, + { + data: true, + onSuccess: (dataArg) => { + dataArg; + }, + error: 500, + onError: (errorArg) => { + errorArg; + }, + }, +]); From 7211b09a41c0c476f05d26e7a23f4ad5f1ef013c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 31 Jul 2024 20:44:30 +0200 Subject: [PATCH 11/23] specialcase negated-like conditional types --- src/compiler/checker.ts | 6 +- ...LikeConstraintInGenericMappedType1.symbols | 117 ++++++++++++++++ ...peLikeConstraintInGenericMappedType1.types | 131 ++++++++++++++++++ ...eConstraintInGenericMappedType2.errors.txt | 35 +++++ ...LikeConstraintInGenericMappedType2.symbols | 95 +++++++++++++ ...peLikeConstraintInGenericMappedType2.types | 126 +++++++++++++++++ ...dTypeLikeConstraintInGenericMappedType1.ts | 47 +++++++ ...dTypeLikeConstraintInGenericMappedType2.ts | 28 ++++ 8 files changed, 584 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.symbols create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.types create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.errors.txt create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.symbols create mode 100644 tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.types create mode 100644 tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts create mode 100644 tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a6f3996586c6b..15e954ab252d3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31611,9 +31611,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, /*noReductions*/ true); function getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t: MappedType) { + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); const constraint = getConstraintTypeFromMappedType(t); + // special case for conditional types pretending to be negated types + if (constraint.flags & TypeFlags.Conditional && getReducedType(getTrueTypeFromConditionalType(constraint as ConditionalType)).flags & TypeFlags.Never && isTypeAssignableTo(propertyNameType, (constraint as ConditionalType).extendsType)) { + return undefined; + } const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { return substituteIndexedMappedType(t, propertyNameType); } diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.symbols b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.symbols new file mode 100644 index 0000000000000..8f282ef5ad271 --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.symbols @@ -0,0 +1,117 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts === +type IntrinsicElements = { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 0, 0)) + + div: { +>div : Symbol(div, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 0, 26)) + + onChange: (ev: Event) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 1, 8)) +>ev : Symbol(ev, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 2, 15)) +>Event : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + }; + span: { +>span : Symbol(span, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 3, 4)) + + onChange: (ev: Event) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 4, 9)) +>ev : Symbol(ev, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 5, 15)) +>Event : Symbol(Event, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + }; +}; + +type ElementType = keyof IntrinsicElements; +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 7, 2)) +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 0, 0)) + +let DEFAULT_TABS_TAG = "div" as const; +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 11, 3)) +>const : Symbol(const) + +type Props = Omit< +>Props : Symbol(Props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 11, 38)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 13, 11)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 7, 2)) +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 13, 36)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) + + IntrinsicElements[TTag], +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 0, 0)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 13, 11)) + + keyof Overrides +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 13, 36)) + +> & + Overrides; +>Overrides : Symbol(Overrides, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 13, 36)) + +type TabGroupProps = Props< +>TabGroupProps : Symbol(TabGroupProps, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 17, 12)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 19, 19)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 7, 2)) +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 11, 3)) +>Props : Symbol(Props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 11, 38)) + + TTag, +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 19, 19)) + { + defaultIndex?: number; +>defaultIndex : Symbol(defaultIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 21, 3)) + + onChange?: (index: number) => void; +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 22, 26)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 23, 16)) + + selectedIndex?: number; +>selectedIndex : Symbol(selectedIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 23, 39)) + + vertical?: boolean; +>vertical : Symbol(vertical, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 24, 27)) + + manual?: boolean; +>manual : Symbol(manual, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 25, 23)) + } +>; + +interface _internal_ComponentTabGroup { +>_internal_ComponentTabGroup : Symbol(_internal_ComponentTabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 28, 2)) + + ( +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 31, 3)) +>ElementType : Symbol(ElementType, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 7, 2)) +>DEFAULT_TABS_TAG : Symbol(DEFAULT_TABS_TAG, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 11, 3)) + + props: TabGroupProps, +>props : Symbol(props, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 31, 55)) +>TabGroupProps : Symbol(TabGroupProps, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 17, 12)) +>TTag : Symbol(TTag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 31, 3)) + + ): null; +} + +declare let TabGroup: _internal_ComponentTabGroup; +>TabGroup : Symbol(TabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 36, 11)) +>_internal_ComponentTabGroup : Symbol(_internal_ComponentTabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 28, 2)) + +TabGroup({ +>TabGroup : Symbol(TabGroup, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 36, 11)) + + defaultIndex: 0, +>defaultIndex : Symbol(defaultIndex, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 38, 10)) + + onChange: (index) => { +>onChange : Symbol(onChange, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 39, 18)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 40, 13)) + + const i: number = index; +>i : Symbol(i, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 41, 9)) +>index : Symbol(index, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts, 40, 13)) + + }, +}); + diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.types b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.types new file mode 100644 index 0000000000000..4b214b1a19519 --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.types @@ -0,0 +1,131 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts === +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 = Omit< +>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/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.errors.txt b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.errors.txt new file mode 100644 index 0000000000000..4313cb5df1d02 --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.errors.txt @@ -0,0 +1,35 @@ +contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts(24,3): error TS2322: Type '(_: any) => string' is not assignable to type 'never'. +contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts(24,7): error TS7006: Parameter '_' implicitly has an 'any' type. + + +==== contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts (2 errors) ==== + type Tags = P extends Record ? X : never; + + declare const typeTags: () => < + P extends { + readonly [Tag in Tags<"_tag", I> & string]: ( + _: Extract, + ) => any; + } & { readonly [Tag in Exclude>]: never }, + >( + fields: P, + ) => unknown; + + type Value = { _tag: "A"; a: number } | { _tag: "B"; b: number }; + const matcher = typeTags(); + + matcher({ + A: (_) => _.a, + B: (_) => "fail", + }); + + matcher({ + A: (_) => _.a, + B: (_) => "fail", + C: (_) => "fail", + ~ +!!! error TS2322: Type '(_: any) => string' is not assignable to type 'never'. + ~ +!!! error TS7006: Parameter '_' implicitly has an 'any' type. + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.symbols b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.symbols new file mode 100644 index 0000000000000..c175ed578a05a --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.symbols @@ -0,0 +1,95 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts === +type Tags = P extends Record ? X : never; +>Tags : Symbol(Tags, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 0)) +>D : Symbol(D, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 10)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 27)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 27)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>D : Symbol(D, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 10)) +>X : Symbol(X, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 58)) +>X : Symbol(X, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 58)) + +declare const typeTags: () => < +>typeTags : Symbol(typeTags, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 13)) +>I : Symbol(I, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 25)) + + P extends { +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 34)) + + readonly [Tag in Tags<"_tag", I> & string]: ( +>Tag : Symbol(Tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 4, 14)) +>Tags : Symbol(Tags, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 0)) +>I : Symbol(I, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 25)) + + _: Extract, +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 4, 49)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>I : Symbol(I, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 25)) +>_tag : Symbol(_tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 5, 21)) +>Tag : Symbol(Tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 4, 14)) + + ) => any; + } & { readonly [Tag in Exclude>]: never }, +>Tag : Symbol(Tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 7, 18)) +>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 34)) +>Tags : Symbol(Tags, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 0, 0)) +>I : Symbol(I, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 25)) + +>( + fields: P, +>fields : Symbol(fields, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 8, 2)) +>P : Symbol(P, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 34)) + +) => unknown; + +type Value = { _tag: "A"; a: number } | { _tag: "B"; b: number }; +>Value : Symbol(Value, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 10, 13)) +>_tag : Symbol(_tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 14)) +>a : Symbol(a, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 25)) +>_tag : Symbol(_tag, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 41)) +>b : Symbol(b, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 52)) + +const matcher = typeTags(); +>matcher : Symbol(matcher, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 13, 5)) +>typeTags : Symbol(typeTags, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 2, 13)) +>Value : Symbol(Value, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 10, 13)) + +matcher({ +>matcher : Symbol(matcher, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 13, 5)) + + A: (_) => _.a, +>A : Symbol(A, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 15, 9)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 16, 6)) +>_.a : Symbol(a, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 25)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 16, 6)) +>a : Symbol(a, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 25)) + + B: (_) => "fail", +>B : Symbol(B, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 16, 16)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 17, 6)) + +}); + +matcher({ +>matcher : Symbol(matcher, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 13, 5)) + + A: (_) => _.a, +>A : Symbol(A, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 20, 9)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 21, 6)) +>_.a : Symbol(a, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 25)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 21, 6)) +>a : Symbol(a, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 12, 25)) + + B: (_) => "fail", +>B : Symbol(B, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 21, 16)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 22, 6)) + + C: (_) => "fail", +>C : Symbol(C, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 22, 19)) +>_ : Symbol(_, Decl(contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts, 23, 6)) + +}); + diff --git a/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.types b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.types new file mode 100644 index 0000000000000..26b6c8f492ad7 --- /dev/null +++ b/tests/baselines/reference/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.types @@ -0,0 +1,126 @@ +//// [tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts] //// + +=== contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts === +type Tags = P extends Record ? X : never; +>Tags : Tags +> : ^^^^^^^^^^ + +declare const typeTags: () => < +>typeTags : () =>

& string]: (_: Extract) => any; } & { readonly [Tag in Exclude>]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^ + + P extends { + readonly [Tag in Tags<"_tag", I> & string]: ( + _: Extract, +>_ : Extract +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ +>_tag : Tag +> : ^^^ + + ) => any; + } & { readonly [Tag in Exclude>]: never }, +>( + fields: P, +>fields : P +> : ^ + +) => unknown; + +type Value = { _tag: "A"; a: number } | { _tag: "B"; b: number }; +>Value : Value +> : ^^^^^ +>_tag : "A" +> : ^^^ +>a : number +> : ^^^^^^ +>_tag : "B" +> : ^^^ +>b : number +> : ^^^^^^ + +const matcher = typeTags(); +>matcher :

any; readonly B: (_: { _tag: "B"; b: number; }) => any; } & { readonly [Tag in Exclude]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ +>typeTags() :

any; readonly B: (_: { _tag: "B"; b: number; }) => any; } & { readonly [Tag in Exclude]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ +>typeTags : () =>

& string]: (_: Extract) => any; } & { readonly [Tag in Exclude>]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^ + +matcher({ +>matcher({ A: (_) => _.a, B: (_) => "fail",}) : unknown +> : ^^^^^^^ +>matcher :

any; readonly B: (_: { _tag: "B"; b: number; }) => any; } & { readonly [Tag in Exclude]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ +>{ A: (_) => _.a, B: (_) => "fail",} : { A: (_: { _tag: "A"; a: number; }) => number; B: (_: { _tag: "B"; b: number; }) => string; } +> : ^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^ + + A: (_) => _.a, +>A : (_: { _tag: "A"; a: number; }) => number +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>(_) => _.a : (_: { _tag: "A"; a: number; }) => number +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>_ : { _tag: "A"; a: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>_.a : number +> : ^^^^^^ +>_ : { _tag: "A"; a: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>a : number +> : ^^^^^^ + + B: (_) => "fail", +>B : (_: { _tag: "B"; b: number; }) => string +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>(_) => "fail" : (_: { _tag: "B"; b: number; }) => string +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>_ : { _tag: "B"; b: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>"fail" : "fail" +> : ^^^^^^ + +}); + +matcher({ +>matcher({ A: (_) => _.a, B: (_) => "fail", C: (_) => "fail",}) : unknown +> : ^^^^^^^ +>matcher :

any; readonly B: (_: { _tag: "B"; b: number; }) => any; } & { readonly [Tag in Exclude]: never; }>(fields: P) => unknown +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^ +>{ A: (_) => _.a, B: (_) => "fail", C: (_) => "fail",} : { A: (_: { _tag: "A"; a: number; }) => number; B: (_: { _tag: "B"; b: number; }) => string; C: (_: any) => string; } +> : ^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ + + A: (_) => _.a, +>A : (_: { _tag: "A"; a: number; }) => number +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>(_) => _.a : (_: { _tag: "A"; a: number; }) => number +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>_ : { _tag: "A"; a: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>_.a : number +> : ^^^^^^ +>_ : { _tag: "A"; a: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>a : number +> : ^^^^^^ + + B: (_) => "fail", +>B : (_: { _tag: "B"; b: number; }) => string +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>(_) => "fail" : (_: { _tag: "B"; b: number; }) => string +> : ^ ^^^^^^^^^^ ^^^^^ ^^^^^^^^^^^^^^ +>_ : { _tag: "B"; b: number; } +> : ^^^^^^^^ ^^^^^ ^^^ +>"fail" : "fail" +> : ^^^^^^ + + C: (_) => "fail", +>C : (_: any) => string +> : ^ ^^^^^^^^^^^^^^^^ +>(_) => "fail" : (_: any) => string +> : ^ ^^^^^^^^^^^^^^^^ +>_ : any +> : ^^^ +>"fail" : "fail" +> : ^^^^^^ + +}); + diff --git a/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts new file mode 100644 index 0000000000000..6851ed2455b90 --- /dev/null +++ b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType1.ts @@ -0,0 +1,47 @@ +// @strict: true +// @noEmit: true + +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 = Omit< + 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; + }, +}); diff --git a/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts new file mode 100644 index 0000000000000..58f38124556c3 --- /dev/null +++ b/tests/cases/compiler/contextualTypesNegatedTypeLikeConstraintInGenericMappedType2.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noEmit: true + +type Tags = P extends Record ? X : never; + +declare const typeTags: () => < + P extends { + readonly [Tag in Tags<"_tag", I> & string]: ( + _: Extract, + ) => any; + } & { readonly [Tag in Exclude>]: never }, +>( + fields: P, +) => unknown; + +type Value = { _tag: "A"; a: number } | { _tag: "B"; b: number }; +const matcher = typeTags(); + +matcher({ + A: (_) => _.a, + B: (_) => "fail", +}); + +matcher({ + A: (_) => _.a, + B: (_) => "fail", + C: (_) => "fail", +}); From 0b89c0f0aa1a5139276f21366f9f0065a7ad5d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 2 Aug 2024 00:04:58 +0200 Subject: [PATCH 12/23] add extra test case --- ...FunctionObjectPropertyIntersection.symbols | 178 ++++++++++-------- ...peFunctionObjectPropertyIntersection.types | 53 ++++++ ...lTypeFunctionObjectPropertyIntersection.ts | 11 ++ 3 files changed, 167 insertions(+), 75 deletions(-) diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols index be048a5ce37e7..57db492d04925 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -84,158 +84,186 @@ createMachine({ }, }); +createMachine({ +>createMachine : Symbol(createMachine, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 13, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 30, 15)) + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 31, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 37)) + + }, + on: { +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 33, 4)) + + "*": (ev) => { +>"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 34, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 35, 10)) + + ev.type; // should be 'FOO' +>ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 37)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 35, 10)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 37)) + + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 29)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 29)) reducers: { [K: string]: (state: string) => void } & { ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 32)) ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 33, 15)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 33, 28)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 32)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 15)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 28)) [K in keyof T]: object; ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 34, 5)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 29)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 5)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 29)) } ): void; createSlice({ ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) f(a) {}, ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 38, 13)) ->a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 4)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 13)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 4)) }); // repro from #49307#issuecomment-1196014488 type Validate = T & { [K in keyof T]: object } ->Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 40, 3)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 26)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 14)) +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 51, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 26)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) declare function f any>>(s: S, x: Validate): void; ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 49)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 21)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 49)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 21)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 48)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 67)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 19)) ->x : Symbol(x, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 72)) ->Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 40, 3)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 21)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 48)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 67)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) +>x : Symbol(x, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 72)) +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 51, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 21)) f(0, { ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 49)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 49)) foo: s => s + 1, ->foo : Symbol(foo, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 47, 6)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 48, 6)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 48, 6)) +>foo : Symbol(foo, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 6)) }) // repro from 49307#issuecomment-1195858950 type SliceCaseReducers = Record State | void>; ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 48)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 23)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 48)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) type ValidateSliceCaseReducers> = ACR & { ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 79)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 79)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) [T in keyof ACR]: ACR[T] extends { ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 3)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 33)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 3)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 3)) reducer(s: S, action?: infer A): any; ->reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 36)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 12)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 31)) ->action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 17)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 32)) +>reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 36)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 12)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) +>action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 17)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 32)) } ? { prepare(...a: never[]): Omit; ->prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 7)) ->a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 16)) +>prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 7)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 71, 16)) >Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 32)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 32)) } : {}; }; declare function createSlice< ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) State, ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) CaseReducers extends SliceCaseReducers ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 8)) ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 8)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) >(options: { ->options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 2)) +>options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 2)) initialState: State | (() => State); ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 12)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 12)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) reducers: ValidateSliceCaseReducers; ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 38)) ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 79)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 29)) ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 8)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 38)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 79)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 8)) }): void; export const clientSlice = createSlice({ ->clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 73, 12)) ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) +>clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 84, 12)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) initialState: { ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 73, 40)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 84, 40)) username: "", ->username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 17)) +>username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 85, 17)) isLoggedIn: false, ->isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 17)) +>isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 86, 17)) userId: "", ->userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 22)) +>userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 22)) avatar: "", ->avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 15)) +>avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 88, 15)) }, reducers: { ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 4)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 90, 4)) onClientUserChanged(state) {}, ->onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 13)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 81, 24)) +>onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 91, 13)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 92, 24)) }, }); diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types index ae8a65a76aaef..8f7412b5536e2 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -105,6 +105,59 @@ createMachine({ }, }); +createMachine({ +>createMachine({ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' }, },}) : void +> : ^^^^ +>createMachine : (config: MachineConfig) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' }, },} : { schema: { events: { type: "FOO"; } | { type: "BAR"; }; }; on: { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { events: { type: "FOO"; } | { type: "BAR"; }; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as { type: "FOO" } | { type: "BAR" }, } : { events: { type: "FOO"; } | { type: "BAR"; }; } +> : ^^^^^^^^^^ ^^^ + + events: {} as { type: "FOO" } | { type: "BAR" }, +>events : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} as { type: "FOO" } | { type: "BAR" } : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ +>type : "FOO" +> : ^^^^^ +>type : "BAR" +> : ^^^^^ + + }, + on: { +>on : { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>{ "*": (ev) => { ev.type; // should be 'FOO' }, } : { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + "*": (ev) => { +>"*" : (ev: { type: "FOO"; } | { type: "BAR"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ +>(ev) => { ev.type; // should be 'FOO' } : (ev: { type: "FOO"; } | { type: "BAR"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ +>ev : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + ev.type; // should be 'FOO' +>ev.type : "FOO" | "BAR" +> : ^^^^^^^^^^^^^ +>ev : { type: "FOO"; } | { type: "BAR"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>type : "FOO" | "BAR" +> : ^^^^^^^^^^^^^ + + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts index db09170d13e95..b148284f50ba9 100644 --- a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -31,6 +31,17 @@ createMachine({ }, }); +createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + "*": (ev) => { + ev.type; // should be 'FOO' + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( From 7e90ef7318d3e2e0133303b644d0e866ec53e93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 2 Aug 2024 08:41:53 +0200 Subject: [PATCH 13/23] just intersect all of them but filter out anys --- src/compiler/checker.ts | 90 +++++++------- ...asedOnIntersectionWithAnyInTheMix1.symbols | 114 ++++++++++++++++++ ...eBasedOnIntersectionWithAnyInTheMix1.types | 89 ++++++++++++++ ...TypeBasedOnIntersectionWithAnyInTheMix1.ts | 38 ++++++ 4 files changed, 286 insertions(+), 45 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.symbols create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.types create mode 100644 tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 15e954ab252d3..b0aa296311c26 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31574,71 +31574,71 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).links.type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); } + function isFilteredOutMappedPropertyName(constraint: Type, propertyNameType: Type): boolean { + if (constraint.flags & TypeFlags.Conditional) { + return !!(getReducedType(getTrueTypeFromConditionalType(constraint as ConditionalType)).flags & TypeFlags.Never) && isTypeAssignableTo(propertyNameType, (constraint as ConditionalType).extendsType); + } + if (constraint.flags & TypeFlags.Intersection) { + return some((constraint as IntersectionType).types, t => isFilteredOutMappedPropertyName(t, propertyNameType)); + } + return false; + } + function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { if (!(t.flags & TypeFlags.StructuredType)) { return undefined; } if (t.flags & TypeFlags.Intersection) { - const intersection = t as IntersectionType; - let applicableIndexedMappedTypeSubstitions: Type[] | undefined; - let concretePropertyTypes: Type[] | undefined; - let applicableIndexInfoCandidates: Type[] | undefined; - for (const t of intersection.types) { - if (isGenericMappedType(t) && !t.declaration.nameType) { - applicableIndexedMappedTypeSubstitions = append(applicableIndexedMappedTypeSubstitions, getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t)); + let types: Type[] | undefined; + for (const constituentType of (t as IntersectionType).types) { + const propertyType = getTypeOfPropertyOfContextualTypeWorker(constituentType); + // any doesn't provide any contextual information but could spoil the overall result by nullifying contextual information provided by other intersection constituents + // at the same time, all types computed based on the contextual information provided by other consistuents are still assignable to any + if (isTypeAny(propertyType)) { continue; } - const typeOfConcreteProperty = getTypeOfConcretePropertyOfContextualType(t); - if (typeOfConcreteProperty) { - concretePropertyTypes = append(concretePropertyTypes, typeOfConcreteProperty); - continue; - } - applicableIndexInfoCandidates = append(applicableIndexInfoCandidates, t); + types = append(types, propertyType); } - if (concretePropertyTypes) { - return getIntersectionType(concatenate(concretePropertyTypes, applicableIndexedMappedTypeSubstitions)); + if (!types) { + return undefined; } - const types = concatenate(mapDefined(applicableIndexInfoCandidates, getTypeOfApplicableIndexInfoOfContextualType), applicableIndexedMappedTypeSubstitions); - if (types.length > 0) { + if (types.length > 1) { return getIntersectionType(types); } - return undefined; + return types[0]; } - return isGenericMappedType(t) && !t.declaration.nameType - ? getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t) - : getTypeOfConcretePropertyOfContextualType(t) || getTypeOfApplicableIndexInfoOfContextualType(t); + return getTypeOfPropertyOfContextualTypeWorker(t); }, /*noReductions*/ true); - function getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t: MappedType) { - const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); - const constraint = getConstraintTypeFromMappedType(t); - // special case for conditional types pretending to be negated types - if (constraint.flags & TypeFlags.Conditional && getReducedType(getTrueTypeFromConditionalType(constraint as ConditionalType)).flags & TypeFlags.Never && isTypeAssignableTo(propertyNameType, (constraint as ConditionalType).extendsType)) { - return undefined; - } - const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { - return substituteIndexedMappedType(t, propertyNameType); - } - return undefined; - } - function getTypeOfConcretePropertyOfContextualType(t: Type) { - const prop = getPropertyOfType(t, name); - if (prop) { - return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional)); + function getTypeOfPropertyOfContextualTypeWorker(t: Type) { + if (isGenericMappedType(t) && !t.declaration.nameType) { + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); + const constraint = getConstraintTypeFromMappedType(t); + // special case for conditional types pretending to be negated types + if (isFilteredOutMappedPropertyName(constraint, propertyNameType)) { + return undefined; + } + const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; + if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { + return substituteIndexedMappedType(t, propertyNameType); + } } - if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { - const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); - if (restType) { - return restType; + else if (t.flags & TypeFlags.StructuredType) { + const prop = getPropertyOfType(t, name); + if (prop) { + return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional)); } + if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { + const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); + if (restType) { + return restType; + } + } + return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } return undefined; } - function getTypeOfApplicableIndexInfoOfContextualType(t: Type) { - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; - } } // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.symbols new file mode 100644 index 0000000000000..3b959ad27842b --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.symbols @@ -0,0 +1,114 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts === +type ComponentType

= (p: P) => any; +>ComponentType : Symbol(ComponentType, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 0)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 19)) +>p : Symbol(p, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 25)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 19)) + +type ComponentProps = C extends ComponentType ? P : never; +>ComponentProps : Symbol(ComponentProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 38)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 20)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 20)) +>ComponentType : Symbol(ComponentType, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 0)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 54)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 54)) + +type Attrs> = A; +>Attrs : Symbol(Attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 70)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 11)) +>A : Symbol(A, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 13)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>P : Symbol(P, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 11)) +>A : Symbol(A, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 13)) + +interface StyledFunction< +>StyledFunction : Symbol(StyledFunction, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 40)) + + C extends ComponentType, +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 5, 25)) +>ComponentType : Symbol(ComponentType, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 0)) + + O extends object = {}, +>O : Symbol(O, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 6, 31)) + + A extends keyof any = never, +>A : Symbol(A, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 7, 24)) + +> { + attrs< +>attrs : Symbol(StyledFunction.attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 9, 3)) + + U, +>U : Symbol(U, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 10, 8)) + + NewA extends Partial & U> & { +>NewA : Symbol(NewA, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 11, 6)) +>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) +>ComponentProps : Symbol(ComponentProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 38)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 5, 25)) +>U : Symbol(U, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 10, 8)) + + [others: string]: any; +>others : Symbol(others, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 13, 7)) + + } = {}, + >( + attrs: Attrs & U, NewA>, +>attrs : Symbol(attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 15, 4)) +>Attrs : Symbol(Attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 1, 70)) +>ComponentProps : Symbol(ComponentProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 38)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 5, 25)) +>U : Symbol(U, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 10, 8)) +>NewA : Symbol(NewA, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 11, 6)) + + ): StyledFunction; +>StyledFunction : Symbol(StyledFunction, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 40)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 5, 25)) +>O : Symbol(O, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 6, 31)) +>NewA : Symbol(NewA, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 11, 6)) +>A : Symbol(A, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 7, 24)) +>NewA : Symbol(NewA, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 11, 6)) +} + +interface StyledInterface { +>StyledInterface : Symbol(StyledInterface, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 18, 1)) + + >(component: C): StyledFunction; +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 21, 3)) +>ComponentType : Symbol(ComponentType, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 0, 0)) +>component : Symbol(component, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 21, 33)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 21, 3)) +>StyledFunction : Symbol(StyledFunction, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 3, 40)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 21, 3)) +} + +declare const styled: StyledInterface; +>styled : Symbol(styled, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 24, 13)) +>StyledInterface : Symbol(StyledInterface, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 18, 1)) + +interface BaseProps { +>BaseProps : Symbol(BaseProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 24, 38)) + + as?: "select" | "input"; +>as : Symbol(BaseProps.as, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 26, 21)) +} + +declare const Flex: (props: BaseProps) => null; +>Flex : Symbol(Flex, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 30, 13)) +>props : Symbol(props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 30, 21)) +>BaseProps : Symbol(BaseProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 24, 38)) + +export const StyledSelect = styled(Flex).attrs({ +>StyledSelect : Symbol(StyledSelect, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 32, 12)) +>styled(Flex).attrs : Symbol(StyledFunction.attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 9, 3)) +>styled : Symbol(styled, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 24, 13)) +>Flex : Symbol(Flex, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 30, 13)) +>attrs : Symbol(StyledFunction.attrs, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 9, 3)) + + as: "select", +>as : Symbol(as, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts, 32, 48)) + +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.types new file mode 100644 index 0000000000000..ae23832fdd9c0 --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix1.types @@ -0,0 +1,89 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts === +type ComponentType

= (p: P) => any; +>ComponentType : ComponentType

+> : ^^^^^^^^^^^^^^^^ +>p : P +> : ^ + +type ComponentProps = C extends ComponentType ? P : never; +>ComponentProps : ComponentProps +> : ^^^^^^^^^^^^^^^^^ + +type Attrs> = A; +>Attrs : A +> : ^ + +interface StyledFunction< + C extends ComponentType, + O extends object = {}, + A extends keyof any = never, +> { + attrs< +>attrs : & U> & { [others: string]: any; } = {}>(attrs: Attrs & U, NewA>) => StyledFunction +> : ^ ^^ ^^^^^^^^^ ^^^^^^^ ^^ ^^^^^ + + U, + NewA extends Partial & U> & { + [others: string]: any; +>others : string +> : ^^^^^^ + + } = {}, + >( + attrs: Attrs & U, NewA>, +>attrs : NewA +> : ^^^^ + + ): StyledFunction; +} + +interface StyledInterface { + >(component: C): StyledFunction; +>component : C +> : ^ +} + +declare const styled: StyledInterface; +>styled : StyledInterface +> : ^^^^^^^^^^^^^^^ + +interface BaseProps { + as?: "select" | "input"; +>as : "select" | "input" | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +declare const Flex: (props: BaseProps) => null; +>Flex : (props: BaseProps) => null +> : ^ ^^ ^^^^^ +>props : BaseProps +> : ^^^^^^^^^ + +export const StyledSelect = styled(Flex).attrs({ +>StyledSelect : StyledFunction<(props: BaseProps) => null, { as: "select"; }, "as"> +> : ^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>styled(Flex).attrs({ as: "select",}) : StyledFunction<(props: BaseProps) => null, { as: "select"; }, "as"> +> : ^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>styled(Flex).attrs : & { [others: string]: any; } = {}>(attrs: NewA) => StyledFunction<(props: BaseProps) => null, {} & NewA, keyof NewA> +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ +>styled(Flex) : StyledFunction<(props: BaseProps) => null, {}, never> +> : ^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^ +>styled : StyledInterface +> : ^^^^^^^^^^^^^^^ +>Flex : (props: BaseProps) => null +> : ^ ^^ ^^^^^ +>attrs : & { [others: string]: any; } = {}>(attrs: NewA) => StyledFunction<(props: BaseProps) => null, {} & NewA, keyof NewA> +> : ^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ +>{ as: "select",} : { as: "select"; } +> : ^^^^^^^^^^^^^^^^^ + + as: "select", +>as : "select" +> : ^^^^^^^^ +>"select" : "select" +> : ^^^^^^^^ + +}); + diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts new file mode 100644 index 0000000000000..9e0d3bc984031 --- /dev/null +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix1.ts @@ -0,0 +1,38 @@ +// @strict: true +// @noEmit: true + +type ComponentType

= (p: P) => any; +type ComponentProps = C extends ComponentType ? P : never; + +type Attrs> = A; + +interface StyledFunction< + C extends ComponentType, + O extends object = {}, + A extends keyof any = never, +> { + attrs< + U, + NewA extends Partial & U> & { + [others: string]: any; + } = {}, + >( + attrs: Attrs & U, NewA>, + ): StyledFunction; +} + +interface StyledInterface { + >(component: C): StyledFunction; +} + +declare const styled: StyledInterface; + +interface BaseProps { + as?: "select" | "input"; +} + +declare const Flex: (props: BaseProps) => null; + +export const StyledSelect = styled(Flex).attrs({ + as: "select", +}); From 01c20d4fba65816172af501b0f8fe002f8a5d552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Aug 2024 02:40:30 +0200 Subject: [PATCH 14/23] go back to retrieving constituents separately --- src/compiler/checker.ts | 108 +++++--- ...asedOnIntersectionWithAnyInTheMix2.symbols | 83 ++++++ ...eBasedOnIntersectionWithAnyInTheMix2.types | 91 +++++++ ...asedOnIntersectionWithAnyInTheMix3.symbols | 55 ++++ ...eBasedOnIntersectionWithAnyInTheMix3.types | 92 +++++++ ...dOnIntersectionWithAnyInTheMix4.errors.txt | 61 +++++ ...asedOnIntersectionWithAnyInTheMix4.symbols | 127 +++++++++ ...eBasedOnIntersectionWithAnyInTheMix4.types | 242 ++++++++++++++++++ ...TypeBasedOnIntersectionWithAnyInTheMix2.ts | 38 +++ ...TypeBasedOnIntersectionWithAnyInTheMix3.ts | 21 ++ ...TypeBasedOnIntersectionWithAnyInTheMix4.ts | 52 ++++ 11 files changed, 931 insertions(+), 39 deletions(-) create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.symbols create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.types create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.errors.txt create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.symbols create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.types create mode 100644 tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts create mode 100644 tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts create mode 100644 tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f92b10a38bb7c..4e5f542fda583 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31589,59 +31589,89 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { - if (!(t.flags & TypeFlags.StructuredType)) { - return undefined; - } if (t.flags & TypeFlags.Intersection) { let types: Type[] | undefined; + let indexInfoCandidates: Type[] | undefined; + let ignoreIndexInfos = false; for (const constituentType of (t as IntersectionType).types) { - const propertyType = getTypeOfPropertyOfContextualTypeWorker(constituentType); - // any doesn't provide any contextual information but could spoil the overall result by nullifying contextual information provided by other intersection constituents - // at the same time, all types computed based on the contextual information provided by other consistuents are still assignable to any - if (isTypeAny(propertyType)) { + if (!(constituentType.flags & TypeFlags.Object)) { continue; } - types = append(types, propertyType); + if (isGenericMappedType(constituentType) && !constituentType.declaration.nameType) { + const substitutedType = getIndexedMappedTypeSubstitutedTypeOfContextualType(constituentType, name, nameType); + types = appendContextualPropertyTypeConsitutent(types, substitutedType); + continue; + } + const propertyType = getTypeOfConcretePropertyOfContextualType(constituentType, name); + if (!propertyType) { + if (!ignoreIndexInfos) { + indexInfoCandidates = append(indexInfoCandidates, constituentType); + } + continue; + } + ignoreIndexInfos = true; + indexInfoCandidates = undefined; + types = appendContextualPropertyTypeConsitutent(types, propertyType); + } + if (indexInfoCandidates) { + for (const candidate of indexInfoCandidates) { + const indexInfoType = getTypeFromIndexInfosOfContextualType(candidate, name, nameType); + types = appendContextualPropertyTypeConsitutent(types, indexInfoType); + } } if (!types) { - return undefined; + return; } - if (types.length > 1) { - return getIntersectionType(types); + if (types.length === 1) { + return types[0]; } - return types[0]; + return getIntersectionType(types); } - return getTypeOfPropertyOfContextualTypeWorker(t); + if (!(t.flags & TypeFlags.Object)) { + return; + } + return isGenericMappedType(t) && !t.declaration.nameType + ? getIndexedMappedTypeSubstitutedTypeOfContextualType(t, name, nameType) + : getTypeOfConcretePropertyOfContextualType(t, name) ?? getTypeFromIndexInfosOfContextualType(t, name, nameType); }, /*noReductions*/ true); + } - function getTypeOfPropertyOfContextualTypeWorker(t: Type) { - if (isGenericMappedType(t) && !t.declaration.nameType) { - const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); - const constraint = getConstraintTypeFromMappedType(t); - // special case for conditional types pretending to be negated types - if (isFilteredOutMappedPropertyName(constraint, propertyNameType)) { - return undefined; - } - const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { - return substituteIndexedMappedType(t, propertyNameType); - } - } - else if (t.flags & TypeFlags.StructuredType) { - const prop = getPropertyOfType(t, name); - if (prop) { - return isCircularMappedProperty(prop) ? undefined : removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional)); - } - if (isTupleType(t) && isNumericLiteralName(name) && +name >= 0) { - const restType = getElementTypeOfSliceOfTupleType(t, t.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); - if (restType) { - return restType; - } - } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; + function appendContextualPropertyTypeConsitutent(types: Type[] | undefined, type: Type | undefined) { + // any doesn't provide any contextual information but could spoil the overall result by nullifying contextual information provided by other intersection constituents + // at the same time, all types computed based on the contextual information provided by other consistuents are still assignable to any + return isTypeAny(type) ? types : append(types, type); + } + + function getIndexedMappedTypeSubstitutedTypeOfContextualType(type: MappedType, name: __String, nameType: Type | undefined) { + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); + const constraint = getConstraintTypeFromMappedType(type); + // special case for conditional types pretending to be negated types + if (isFilteredOutMappedPropertyName(constraint, propertyNameType)) { + return; + } + const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; + if (!isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { + return; + } + return substituteIndexedMappedType(type, propertyNameType); + } + + function getTypeOfConcretePropertyOfContextualType(type: Type, name: __String) { + const prop = getPropertyOfType(type, name); + if (!prop || isCircularMappedProperty(prop)) { + return; + } + return removeMissingType(getTypeOfSymbol(prop), !!(prop.flags & SymbolFlags.Optional)); + } + + function getTypeFromIndexInfosOfContextualType(type: Type, name: __String, nameType: Type | undefined) { + if (isTupleType(type) && isNumericLiteralName(name) && +name >= 0) { + const restType = getElementTypeOfSliceOfTupleType(type, type.target.fixedLength, /*endSkipCount*/ 0, /*writing*/ false, /*noReductions*/ true); + if (restType) { + return restType; } - return undefined; } + return findApplicableIndexInfo(getIndexInfosOfStructuredType(type), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.symbols new file mode 100644 index 0000000000000..0776e0ce7aa2e --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.symbols @@ -0,0 +1,83 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts === +type IntrinsicElements = { +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 0, 0)) + + a: { +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 0, 26)) + + href?: string; +>href : Symbol(href, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 1, 6)) + + }; + div: { +>div : Symbol(div, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 3, 4)) + + dir?: string; +>dir : Symbol(dir, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 4, 8)) + + }; +}; + +type Component = (props: Props) => unknown; +>Component : Symbol(Component, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 7, 2)) +>Props : Symbol(Props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 9, 15)) +>props : Symbol(props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 9, 25)) +>Props : Symbol(Props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 9, 15)) + +interface NestedMDXComponents { +>NestedMDXComponents : Symbol(NestedMDXComponents, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 9, 50)) + + [key: string]: Component; +>key : Symbol(key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 12, 3)) +>Component : Symbol(Component, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 7, 2)) +} + +type MDXComponents = NestedMDXComponents & { +>MDXComponents : Symbol(MDXComponents, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 13, 1)) +>NestedMDXComponents : Symbol(NestedMDXComponents, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 9, 50)) + + [Key in keyof IntrinsicElements]?: Component; +>Key : Symbol(Key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 16, 3)) +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 0, 0)) +>Component : Symbol(Component, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 7, 2)) +>IntrinsicElements : Symbol(IntrinsicElements, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 0, 0)) +>Key : Symbol(Key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 16, 3)) + +}; + +export interface MDXProps { +>MDXProps : Symbol(MDXProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 17, 2)) + + components?: MDXComponents; +>components : Symbol(MDXProps.components, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 19, 27)) +>MDXComponents : Symbol(MDXComponents, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 13, 1)) +} + +declare function MyMDXComponent(props: MDXProps): null; +>MyMDXComponent : Symbol(MyMDXComponent, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 21, 1)) +>props : Symbol(props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 23, 32)) +>MDXProps : Symbol(MDXProps, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 17, 2)) + +MyMDXComponent({ +>MyMDXComponent : Symbol(MyMDXComponent, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 21, 1)) + + components: { +>components : Symbol(components, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 25, 16)) + + a(props) { +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 26, 15)) +>props : Symbol(props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 27, 6)) + + return null; + }, + div(props) { +>div : Symbol(div, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 29, 6)) +>props : Symbol(props, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts, 30, 8)) + + return null; + }, + }, +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.types new file mode 100644 index 0000000000000..d29a47924fbe0 --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix2.types @@ -0,0 +1,91 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts === +type IntrinsicElements = { +>IntrinsicElements : IntrinsicElements +> : ^^^^^^^^^^^^^^^^^ + + a: { +>a : { href?: string; } +> : ^^^^^^^^^ ^^^ + + href?: string; +>href : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }; + div: { +>div : { dir?: string; } +> : ^^^^^^^^ ^^^ + + dir?: string; +>dir : string | undefined +> : ^^^^^^^^^^^^^^^^^^ + + }; +}; + +type Component = (props: Props) => unknown; +>Component : Component +> : ^^^^^^^^^^^^^^^^ +>props : Props +> : ^^^^^ + +interface NestedMDXComponents { + [key: string]: Component; +>key : string +> : ^^^^^^ +} + +type MDXComponents = NestedMDXComponents & { +>MDXComponents : MDXComponents +> : ^^^^^^^^^^^^^ + + [Key in keyof IntrinsicElements]?: Component; +}; + +export interface MDXProps { + components?: MDXComponents; +>components : MDXComponents | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +declare function MyMDXComponent(props: MDXProps): null; +>MyMDXComponent : (props: MDXProps) => null +> : ^ ^^ ^^^^^ +>props : MDXProps +> : ^^^^^^^^ + +MyMDXComponent({ +>MyMDXComponent({ components: { a(props) { return null; }, div(props) { return null; }, },}) : null +> : ^^^^ +>MyMDXComponent : (props: MDXProps) => null +> : ^ ^^ ^^^^^ +>{ components: { a(props) { return null; }, div(props) { return null; }, },} : { components: { a(props: { href?: string; }): null; div(props: { dir?: string; }): null; }; } +> : ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ + + components: { +>components : { a(props: { href?: string; }): null; div(props: { dir?: string; }): null; } +> : ^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^ +>{ a(props) { return null; }, div(props) { return null; }, } : { a(props: { href?: string; }): null; div(props: { dir?: string; }): null; } +> : ^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^ + + a(props) { +>a : (props: { href?: string; }) => null +> : ^ ^^^^^^^^^^^ ^^^^^^^^^^^^ +>props : { href?: string; } +> : ^^^^^^^^^ ^^^ + + return null; + }, + div(props) { +>div : (props: { dir?: string; }) => null +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^ +>props : { dir?: string; } +> : ^^^^^^^^ ^^^ + + return null; + }, + }, +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols new file mode 100644 index 0000000000000..8404ab79734bf --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts === +type TypeMap = { +>TypeMap : Symbol(TypeMap, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 0, 0)) + + str: "a" | "b" | "c"; +>str : Symbol(str, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 0, 16)) + + num: 1 | 2 | 3; +>num : Symbol(num, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 1, 23)) + +}; + +declare function test1< +>test1 : Symbol(test1, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 3, 2)) + + T extends { [K in keyof TypeMap]: TypeMap[K][] } & { [k: string]: any[] }, +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 5, 23)) +>K : Symbol(K, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 6, 15)) +>TypeMap : Symbol(TypeMap, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 0, 0)) +>TypeMap : Symbol(TypeMap, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 0, 0)) +>K : Symbol(K, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 6, 15)) +>k : Symbol(k, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 6, 56)) + +>(arg: T): T; +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 7, 2)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 5, 23)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 5, 23)) + +const result = test1({ +>result : Symbol(result, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 9, 5)) +>test1 : Symbol(test1, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 3, 2)) + + num: [1, 2], +>num : Symbol(num, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 9, 22)) + + str: ["a", "b"], +>str : Symbol(str, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 10, 14)) + + bool: [true, false], +>bool : Symbol(bool, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 11, 18)) + +}); + +declare function test2(a: { type: "foo" | "bar" } & { type: any }): void; +>test2 : Symbol(test2, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 13, 3)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 15, 23)) +>type : Symbol(type, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 15, 27)) +>type : Symbol(type, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 15, 53)) + +test2({ type: "foo" }); +>test2 : Symbol(test2, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 13, 3)) +>type : Symbol(type, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 17, 7)) + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types new file mode 100644 index 0000000000000..4a1e35ad4534a --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types @@ -0,0 +1,92 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts === +type TypeMap = { +>TypeMap : TypeMap +> : ^^^^^^^ + + str: "a" | "b" | "c"; +>str : "a" | "b" | "c" +> : ^^^^^^^^^^^^^^^ + + num: 1 | 2 | 3; +>num : 1 | 2 | 3 +> : ^^^^^^^^^ + +}; + +declare function test1< +>test1 : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ + + T extends { [K in keyof TypeMap]: TypeMap[K][] } & { [k: string]: any[] }, +>k : string +> : ^^^^^^ + +>(arg: T): T; +>arg : T +> : ^ + +const result = test1({ +>result : { num: (1 | 2)[]; str: ("a" | "b")[]; bool: boolean[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test1({ num: [1, 2], str: ["a", "b"], bool: [true, false],}) : { num: (1 | 2)[]; str: ("a" | "b")[]; bool: boolean[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>test1 : (arg: T) => T +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ num: [1, 2], str: ["a", "b"], bool: [true, false],} : { num: (1 | 2)[]; str: ("a" | "b")[]; bool: boolean[]; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + num: [1, 2], +>num : (1 | 2)[] +> : ^^^^^^^^^ +>[1, 2] : (1 | 2)[] +> : ^^^^^^^^^ +>1 : 1 +> : ^ +>2 : 2 +> : ^ + + str: ["a", "b"], +>str : ("a" | "b")[] +> : ^^^^^^^^^^^^^ +>["a", "b"] : ("a" | "b")[] +> : ^^^^^^^^^^^^^ +>"a" : "a" +> : ^^^ +>"b" : "b" +> : ^^^ + + bool: [true, false], +>bool : boolean[] +> : ^^^^^^^^^ +>[true, false] : boolean[] +> : ^^^^^^^^^ +>true : true +> : ^^^^ +>false : false +> : ^^^^^ + +}); + +declare function test2(a: { type: "foo" | "bar" } & { type: any }): void; +>test2 : (a: { type: "foo" | "bar"; } & { type: any; }) => void +> : ^ ^^ ^^^^^ +>a : { type: "foo" | "bar"; } & { type: any; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>type : "foo" | "bar" +> : ^^^^^^^^^^^^^ +>type : any + +test2({ type: "foo" }); +>test2({ type: "foo" }) : void +> : ^^^^ +>test2 : (a: { type: "foo" | "bar"; } & { type: any; }) => void +> : ^ ^^ ^^^^^ +>{ type: "foo" } : { type: "foo"; } +> : ^^^^^^^^^^^^^^^^ +>type : "foo" +> : ^^^^^ +>"foo" : "foo" +> : ^^^^^ + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.errors.txt b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.errors.txt new file mode 100644 index 0000000000000..70a344908035e --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.errors.txt @@ -0,0 +1,61 @@ +contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts(33,12): error TS2322: Type '"bar"' is not assignable to type '"foo"'. +contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts(48,15): error TS2322: Type '"bar"' is not assignable to type '"foo"'. + + +==== contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts (2 errors) ==== + declare function test1( + arg: { a: (arg: number) => void } & { [k: string]: (arg: any) => void }, + ): unknown; + + test1({ + a: (arg) => {}, + b: (arg) => {}, + }); + + declare function test2( + arg: { a: (arg: { foo: string }) => void } & { + [k: string]: (arg: { foo: any }) => void; + }, + ): unknown; + + test2({ + a: (arg) => {}, + b: (arg) => {}, + }); + + declare function test3( + arg: { a: () => "foo" } & { + [k: string]: () => any; + }, + ): unknown; + + test3({ + a: () => "foo", + b: () => "bar", + }); + + test3({ + a: () => "bar", + ~~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6502 contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts:22:13: The expected type comes from the return type of this signature. + }); + + declare function test4( + arg: { a: () => { prop: "foo" } } & { + [k: string]: () => { prop: any }; + }, + ): unknown; + + test4({ + a: () => ({ prop: "foo" }), + b: () => ({ prop: "bar" }), + }); + + test4({ + a: () => ({ prop: "bar" }), + ~~~~ +!!! error TS2322: Type '"bar"' is not assignable to type '"foo"'. +!!! related TS6500 contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts:37:21: The expected type comes from property 'prop' which is declared here on type '{ prop: "foo"; }' + }); + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.symbols new file mode 100644 index 0000000000000..0114a153b5047 --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.symbols @@ -0,0 +1,127 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts === +declare function test1( +>test1 : Symbol(test1, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 0, 0)) + + arg: { a: (arg: number) => void } & { [k: string]: (arg: any) => void }, +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 0, 23)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 1, 8)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 1, 13)) +>k : Symbol(k, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 1, 41)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 1, 54)) + +): unknown; + +test1({ +>test1 : Symbol(test1, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 0, 0)) + + a: (arg) => {}, +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 4, 7)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 5, 6)) + + b: (arg) => {}, +>b : Symbol(b, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 5, 17)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 6, 6)) + +}); + +declare function test2( +>test2 : Symbol(test2, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 7, 3)) + + arg: { a: (arg: { foo: string }) => void } & { +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 9, 23)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 10, 8)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 10, 13)) +>foo : Symbol(foo, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 10, 19)) + + [k: string]: (arg: { foo: any }) => void; +>k : Symbol(k, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 11, 5)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 11, 18)) +>foo : Symbol(foo, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 11, 24)) + + }, +): unknown; + +test2({ +>test2 : Symbol(test2, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 7, 3)) + + a: (arg) => {}, +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 15, 7)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 16, 6)) + + b: (arg) => {}, +>b : Symbol(b, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 16, 17)) +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 17, 6)) + +}); + +declare function test3( +>test3 : Symbol(test3, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 18, 3)) + + arg: { a: () => "foo" } & { +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 20, 23)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 21, 8)) + + [k: string]: () => any; +>k : Symbol(k, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 22, 5)) + + }, +): unknown; + +test3({ +>test3 : Symbol(test3, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 18, 3)) + + a: () => "foo", +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 26, 7)) + + b: () => "bar", +>b : Symbol(b, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 27, 17)) + +}); + +test3({ +>test3 : Symbol(test3, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 18, 3)) + + a: () => "bar", +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 31, 7)) + +}); + +declare function test4( +>test4 : Symbol(test4, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 33, 3)) + + arg: { a: () => { prop: "foo" } } & { +>arg : Symbol(arg, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 35, 23)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 36, 8)) +>prop : Symbol(prop, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 36, 19)) + + [k: string]: () => { prop: any }; +>k : Symbol(k, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 37, 5)) +>prop : Symbol(prop, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 37, 24)) + + }, +): unknown; + +test4({ +>test4 : Symbol(test4, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 33, 3)) + + a: () => ({ prop: "foo" }), +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 41, 7)) +>prop : Symbol(prop, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 42, 13)) + + b: () => ({ prop: "bar" }), +>b : Symbol(b, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 42, 29)) +>prop : Symbol(prop, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 43, 13)) + +}); + +test4({ +>test4 : Symbol(test4, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 33, 3)) + + a: () => ({ prop: "bar" }), +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 46, 7)) +>prop : Symbol(prop, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts, 47, 13)) + +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.types new file mode 100644 index 0000000000000..8900e319846d9 --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix4.types @@ -0,0 +1,242 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts === +declare function test1( +>test1 : (arg: { a: (arg: number) => void; } & { [k: string]: (arg: any) => void; }) => unknown +> : ^ ^^ ^^^^^ + + arg: { a: (arg: number) => void } & { [k: string]: (arg: any) => void }, +>arg : { a: (arg: number) => void; } & { [k: string]: (arg: any) => void; } +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^ +>a : (arg: number) => void +> : ^ ^^ ^^^^^ +>arg : number +> : ^^^^^^ +>k : string +> : ^^^^^^ +>arg : any +> : ^^^ + +): unknown; + +test1({ +>test1({ a: (arg) => {}, b: (arg) => {},}) : unknown +> : ^^^^^^^ +>test1 : (arg: { a: (arg: number) => void; } & { [k: string]: (arg: any) => void; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: (arg) => {}, b: (arg) => {},} : { a: (arg: number) => void; b: (arg: any) => void; } +> : ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ + + a: (arg) => {}, +>a : (arg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>(arg) => {} : (arg: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>arg : number +> : ^^^^^^ + + b: (arg) => {}, +>b : (arg: any) => void +> : ^ ^^^^^^^^^^^^^^ +>(arg) => {} : (arg: any) => void +> : ^ ^^^^^^^^^^^^^^ +>arg : any +> : ^^^ + +}); + +declare function test2( +>test2 : (arg: { a: (arg: { foo: string; }) => void; } & { [k: string]: (arg: { foo: any; }) => void; }) => unknown +> : ^ ^^ ^^^^^ + + arg: { a: (arg: { foo: string }) => void } & { +>arg : { a: (arg: { foo: string; }) => void; } & { [k: string]: (arg: { foo: any; }) => void; } +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^^^ +>a : (arg: { foo: string; }) => void +> : ^ ^^ ^^^^^ +>arg : { foo: string; } +> : ^^^^^^^ ^^^ +>foo : string +> : ^^^^^^ + + [k: string]: (arg: { foo: any }) => void; +>k : string +> : ^^^^^^ +>arg : { foo: any; } +> : ^^^^^^^ ^^^ +>foo : any +> : ^^^ + + }, +): unknown; + +test2({ +>test2({ a: (arg) => {}, b: (arg) => {},}) : unknown +> : ^^^^^^^ +>test2 : (arg: { a: (arg: { foo: string; }) => void; } & { [k: string]: (arg: { foo: any; }) => void; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: (arg) => {}, b: (arg) => {},} : { a: (arg: { foo: string; }) => void; b: (arg: { foo: any; }) => void; } +> : ^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^ + + a: (arg) => {}, +>a : (arg: { foo: string; }) => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^ +>(arg) => {} : (arg: { foo: string; }) => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^ +>arg : { foo: string; } +> : ^^^^^^^ ^^^ + + b: (arg) => {}, +>b : (arg: { foo: any; }) => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^ +>(arg) => {} : (arg: { foo: any; }) => void +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^ +>arg : { foo: any; } +> : ^^^^^^^ ^^^ + +}); + +declare function test3( +>test3 : (arg: { a: () => "foo"; } & { [k: string]: () => any; }) => unknown +> : ^ ^^ ^^^^^ + + arg: { a: () => "foo" } & { +>arg : { a: () => "foo"; } & { [k: string]: () => any; } +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>a : () => "foo" +> : ^^^^^^ + + [k: string]: () => any; +>k : string +> : ^^^^^^ + + }, +): unknown; + +test3({ +>test3({ a: () => "foo", b: () => "bar",}) : unknown +> : ^^^^^^^ +>test3 : (arg: { a: () => "foo"; } & { [k: string]: () => any; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: () => "foo", b: () => "bar",} : { a: () => "foo"; b: () => string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a: () => "foo", +>a : () => "foo" +> : ^^^^^^^^^^^ +>() => "foo" : () => "foo" +> : ^^^^^^^^^^^ +>"foo" : "foo" +> : ^^^^^ + + b: () => "bar", +>b : () => string +> : ^^^^^^^^^^^^ +>() => "bar" : () => string +> : ^^^^^^^^^^^^ +>"bar" : "bar" +> : ^^^^^ + +}); + +test3({ +>test3({ a: () => "bar",}) : unknown +> : ^^^^^^^ +>test3 : (arg: { a: () => "foo"; } & { [k: string]: () => any; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: () => "bar",} : { a: () => "bar"; } +> : ^^^^^^^^^^^^^^^^^^^ + + a: () => "bar", +>a : () => "bar" +> : ^^^^^^^^^^^ +>() => "bar" : () => "bar" +> : ^^^^^^^^^^^ +>"bar" : "bar" +> : ^^^^^ + +}); + +declare function test4( +>test4 : (arg: { a: () => { prop: "foo"; }; } & { [k: string]: () => { prop: any; }; }) => unknown +> : ^ ^^ ^^^^^ + + arg: { a: () => { prop: "foo" } } & { +>arg : { a: () => { prop: "foo"; }; } & { [k: string]: () => { prop: any; }; } +> : ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^ +>a : () => { prop: "foo"; } +> : ^^^^^^ +>prop : "foo" +> : ^^^^^ + + [k: string]: () => { prop: any }; +>k : string +> : ^^^^^^ +>prop : any +> : ^^^ + + }, +): unknown; + +test4({ +>test4({ a: () => ({ prop: "foo" }), b: () => ({ prop: "bar" }),}) : unknown +> : ^^^^^^^ +>test4 : (arg: { a: () => { prop: "foo"; }; } & { [k: string]: () => { prop: any; }; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: () => ({ prop: "foo" }), b: () => ({ prop: "bar" }),} : { a: () => { prop: "foo"; }; b: () => { prop: string; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a: () => ({ prop: "foo" }), +>a : () => { prop: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>() => ({ prop: "foo" }) : () => { prop: "foo"; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>({ prop: "foo" }) : { prop: "foo"; } +> : ^^^^^^^^^^^^^^^^ +>{ prop: "foo" } : { prop: "foo"; } +> : ^^^^^^^^^^^^^^^^ +>prop : "foo" +> : ^^^^^ +>"foo" : "foo" +> : ^^^^^ + + b: () => ({ prop: "bar" }), +>b : () => { prop: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>() => ({ prop: "bar" }) : () => { prop: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>({ prop: "bar" }) : { prop: string; } +> : ^^^^^^^^^^^^^^^^^ +>{ prop: "bar" } : { prop: string; } +> : ^^^^^^^^^^^^^^^^^ +>prop : string +> : ^^^^^^ +>"bar" : "bar" +> : ^^^^^ + +}); + +test4({ +>test4({ a: () => ({ prop: "bar" }),}) : unknown +> : ^^^^^^^ +>test4 : (arg: { a: () => { prop: "foo"; }; } & { [k: string]: () => { prop: any; }; }) => unknown +> : ^ ^^ ^^^^^ +>{ a: () => ({ prop: "bar" }),} : { a: () => { prop: "bar"; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + a: () => ({ prop: "bar" }), +>a : () => { prop: "bar"; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>() => ({ prop: "bar" }) : () => { prop: "bar"; } +> : ^^^^^^^^^^^^^^^^^^^^^^ +>({ prop: "bar" }) : { prop: "bar"; } +> : ^^^^^^^^^^^^^^^^ +>{ prop: "bar" } : { prop: "bar"; } +> : ^^^^^^^^^^^^^^^^ +>prop : "bar" +> : ^^^^^ +>"bar" : "bar" +> : ^^^^^ + +}); + diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts new file mode 100644 index 0000000000000..efa68a4854663 --- /dev/null +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix2.ts @@ -0,0 +1,38 @@ +// @strict: true +// @noEmit: true + +type IntrinsicElements = { + a: { + href?: string; + }; + div: { + dir?: string; + }; +}; + +type Component = (props: Props) => unknown; + +interface NestedMDXComponents { + [key: string]: Component; +} + +type MDXComponents = NestedMDXComponents & { + [Key in keyof IntrinsicElements]?: Component; +}; + +export interface MDXProps { + components?: MDXComponents; +} + +declare function MyMDXComponent(props: MDXProps): null; + +MyMDXComponent({ + components: { + a(props) { + return null; + }, + div(props) { + return null; + }, + }, +}); diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts new file mode 100644 index 0000000000000..70e82aefc3135 --- /dev/null +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts @@ -0,0 +1,21 @@ +// @strict: true +// @noEmit: true + +type TypeMap = { + str: "a" | "b" | "c"; + num: 1 | 2 | 3; +}; + +declare function test1< + T extends { [K in keyof TypeMap]: TypeMap[K][] } & { [k: string]: any[] }, +>(arg: T): T; + +const result = test1({ + num: [1, 2], + str: ["a", "b"], + bool: [true, false], +}); + +declare function test2(a: { type: "foo" | "bar" } & { type: any }): void; + +test2({ type: "foo" }); diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts new file mode 100644 index 0000000000000..c43a322a29620 --- /dev/null +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix4.ts @@ -0,0 +1,52 @@ +// @strict: true +// @noEmit: true + +declare function test1( + arg: { a: (arg: number) => void } & { [k: string]: (arg: any) => void }, +): unknown; + +test1({ + a: (arg) => {}, + b: (arg) => {}, +}); + +declare function test2( + arg: { a: (arg: { foo: string }) => void } & { + [k: string]: (arg: { foo: any }) => void; + }, +): unknown; + +test2({ + a: (arg) => {}, + b: (arg) => {}, +}); + +declare function test3( + arg: { a: () => "foo" } & { + [k: string]: () => any; + }, +): unknown; + +test3({ + a: () => "foo", + b: () => "bar", +}); + +test3({ + a: () => "bar", +}); + +declare function test4( + arg: { a: () => { prop: "foo" } } & { + [k: string]: () => { prop: any }; + }, +): unknown; + +test4({ + a: () => ({ prop: "foo" }), + b: () => ({ prop: "bar" }), +}); + +test4({ + a: () => ({ prop: "bar" }), +}); From b0012cf2d51d4e89c64c79bdc0d2bd79e53ebada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Aug 2024 10:59:17 +0200 Subject: [PATCH 15/23] add an extra test case --- ...ypeBasedOnIntersectionWithAnyInTheMix3.symbols | 8 ++++++++ ...lTypeBasedOnIntersectionWithAnyInTheMix3.types | 15 +++++++++++++++ ...tualTypeBasedOnIntersectionWithAnyInTheMix3.ts | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols index 8404ab79734bf..e4e424d5a2589 100644 --- a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols @@ -53,3 +53,11 @@ test2({ type: "foo" }); >test2 : Symbol(test2, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 13, 3)) >type : Symbol(type, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 17, 7)) +// https://github.com/microsoft/TypeScript/issues/59473 + +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } +>x : Symbol(x, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 5)) +>ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 10)) +>ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 24)) +>ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 41)) + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types index 4a1e35ad4534a..d9dff7c007a0f 100644 --- a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types @@ -90,3 +90,18 @@ test2({ type: "foo" }); >"foo" : "foo" > : ^^^^^ +// https://github.com/microsoft/TypeScript/issues/59473 + +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } +>x : { ml: any; } & { ml: "edge"; } +> : ^^^^^^ ^^^^^^^^^^^^ ^^^ +>ml : any +>ml : "edge" +> : ^^^^^^ +>{ ml: 'edge' } : { ml: "edge"; } +> : ^^^^^^^^^^^^^^^ +>ml : "edge" +> : ^^^^^^ +>'edge' : "edge" +> : ^^^^^^ + diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts index 70e82aefc3135..35515546316f3 100644 --- a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts @@ -19,3 +19,7 @@ const result = test1({ declare function test2(a: { type: "foo" | "bar" } & { type: any }): void; test2({ type: "foo" }); + +// https://github.com/microsoft/TypeScript/issues/59473 + +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } From a1c7ba192cdd13f636ea1936feb9467ca5beb56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Aug 2024 19:35:34 +0200 Subject: [PATCH 16/23] add extra test cases --- ...asedOnIntersectionWithAnyInTheMix3.symbols | 24 ++++++++- ...eBasedOnIntersectionWithAnyInTheMix3.types | 54 ++++++++++++++++++- ...TypeBasedOnIntersectionWithAnyInTheMix3.ts | 8 ++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols index e4e424d5a2589..39658147169d7 100644 --- a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.symbols @@ -55,9 +55,31 @@ test2({ type: "foo" }); // https://github.com/microsoft/TypeScript/issues/59473 -const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' }; >x : Symbol(x, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 5)) >ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 10)) >ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 24)) >ml : Symbol(ml, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 21, 41)) +const a: [any] & [1] = [1]; +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 22, 5)) + +const b: any[] & 1[] = [1, 1]; +>b : Symbol(b, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 23, 5)) + +const c: { a: any } & { a: 1 } = { a: 1 }; +>c : Symbol(c, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 24, 5)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 24, 10)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 24, 23)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 24, 34)) + +const d: (() => { a: 1 }) & (() => { a: any }) = () => ({ +>d : Symbol(d, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 25, 5)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 25, 17)) +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 25, 36)) + + a: 1, +>a : Symbol(a, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts, 25, 57)) + +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types index d9dff7c007a0f..c5ac24db84967 100644 --- a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix3.types @@ -92,7 +92,7 @@ test2({ type: "foo" }); // https://github.com/microsoft/TypeScript/issues/59473 -const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' }; >x : { ml: any; } & { ml: "edge"; } > : ^^^^^^ ^^^^^^^^^^^^ ^^^ >ml : any @@ -105,3 +105,55 @@ const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } >'edge' : "edge" > : ^^^^^^ +const a: [any] & [1] = [1]; +>a : [any] & [1] +> : ^^^^^^^^^^^ +>[1] : [1] +> : ^^^ +>1 : 1 +> : ^ + +const b: any[] & 1[] = [1, 1]; +>b : any[] & 1[] +> : ^^^^^^^^^^^ +>[1, 1] : 1[] +> : ^^^ +>1 : 1 +> : ^ +>1 : 1 +> : ^ + +const c: { a: any } & { a: 1 } = { a: 1 }; +>c : { a: any; } & { a: 1; } +> : ^^^^^ ^^^^^^^^^^^ ^^^ +>a : any +>a : 1 +> : ^ +>{ a: 1 } : { a: 1; } +> : ^^^^^^^^^ +>a : 1 +> : ^ +>1 : 1 +> : ^ + +const d: (() => { a: 1 }) & (() => { a: any }) = () => ({ +>d : (() => { a: 1; }) & (() => { a: any; }) +> : ^^^^^^^ ^^^^^^^^^^^ ^ +>a : 1 +> : ^ +>a : any +>() => ({ a: 1,}) : () => { a: 1; } +> : ^^^^^^^^^^^^^^^ +>({ a: 1,}) : { a: 1; } +> : ^^^^^^^^^ +>{ a: 1,} : { a: 1; } +> : ^^^^^^^^^ + + a: 1, +>a : 1 +> : ^ +>1 : 1 +> : ^ + +}); + diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts index 35515546316f3..42113a86f5775 100644 --- a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix3.ts @@ -22,4 +22,10 @@ test2({ type: "foo" }); // https://github.com/microsoft/TypeScript/issues/59473 -const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' } +const x: { ml: any } & { ml: 'edge' } = { ml: 'edge' }; +const a: [any] & [1] = [1]; +const b: any[] & 1[] = [1, 1]; +const c: { a: any } & { a: 1 } = { a: 1 }; +const d: (() => { a: 1 }) & (() => { a: any }) = () => ({ + a: 1, +}); From e3f9169989481fed52a8d8fc69a2e80daf994f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Aug 2024 23:46:57 +0200 Subject: [PATCH 17/23] return `unknown` when no consistuent property types are found for intersections --- src/compiler/checker.ts | 2 +- ...asedOnIntersectionWithAnyInTheMix5.symbols | 167 ++++++++++++++++++ ...eBasedOnIntersectionWithAnyInTheMix5.types | 148 ++++++++++++++++ ...TypeBasedOnIntersectionWithAnyInTheMix5.ts | 59 +++++++ 4 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.symbols create mode 100644 tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.types create mode 100644 tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4e5f542fda583..798c85d4916ae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31620,7 +31620,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (!types) { - return; + return unknownType; } if (types.length === 1) { return types[0]; diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.symbols b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.symbols new file mode 100644 index 0000000000000..aa654c54653c8 --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.symbols @@ -0,0 +1,167 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts === +type ComputedGetter = (oldValue?: T) => T; +>ComputedGetter : Symbol(ComputedGetter, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 0)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 20)) +>oldValue : Symbol(oldValue, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 26)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 20)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 20)) + +type ComputedOptions = Record>; +>ComputedOptions : Symbol(ComputedOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 45)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>ComputedGetter : Symbol(ComputedGetter, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 0)) + +type ExtractComputedReturns = { +>ExtractComputedReturns : Symbol(ExtractComputedReturns, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 1, 59)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 3, 28)) + + [key in keyof T]: T[key] extends (...args: any[]) => infer TReturn +>key : Symbol(key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 4, 3)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 3, 28)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 3, 28)) +>key : Symbol(key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 4, 3)) +>args : Symbol(args, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 4, 36)) +>TReturn : Symbol(TReturn, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 4, 60)) + + ? TReturn +>TReturn : Symbol(TReturn, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 4, 60)) + + : never; +}; + +interface ComponentOptionsBase { +>ComponentOptionsBase : Symbol(ComponentOptionsBase, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 7, 2)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 9, 31)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 9, 33)) +>ComputedOptions : Symbol(ComputedOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 45)) + + data?: D; +>data : Symbol(ComponentOptionsBase.data, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 9, 62)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 9, 31)) + + computed?: C; +>computed : Symbol(ComponentOptionsBase.computed, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 10, 11)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 9, 33)) +} + +type ComponentPublicInstance = D & +>ComponentPublicInstance : Symbol(ComponentPublicInstance, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 12, 1)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 14, 29)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 14, 36)) +>ComputedOptions : Symbol(ComputedOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 45)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 14, 29)) + + ExtractComputedReturns; +>ExtractComputedReturns : Symbol(ExtractComputedReturns, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 1, 59)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 14, 36)) + +type ComponentOptions< +>ComponentOptions : Symbol(ComponentOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 15, 28)) + + D = any, +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 17, 22)) + + C extends ComputedOptions = any, +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 18, 10)) +>ComputedOptions : Symbol(ComputedOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 0, 45)) + +> = ComponentOptionsBase & ThisType>; +>ComponentOptionsBase : Symbol(ComponentOptionsBase, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 7, 2)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 17, 22)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 18, 10)) +>ThisType : Symbol(ThisType, Decl(lib.es5.d.ts, --, --)) +>ComponentPublicInstance : Symbol(ComponentPublicInstance, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 12, 1)) +>D : Symbol(D, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 17, 22)) +>C : Symbol(C, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 18, 10)) + +interface App { +>App : Symbol(App, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 20, 73)) + + mixin(mixin: ComponentOptions): this; +>mixin : Symbol(App.mixin, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 22, 15)) +>mixin : Symbol(mixin, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 23, 8)) +>ComponentOptions : Symbol(ComponentOptions, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 15, 28)) +} + +interface InjectionKey extends Symbol {} +>InjectionKey : Symbol(InjectionKey, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 24, 1)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 26, 23)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --)) + +interface Ref { +>Ref : Symbol(Ref, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 26, 43)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 28, 14)) + + _v: T; +>_v : Symbol(Ref._v, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 28, 18)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 28, 14)) +} + +declare function reactive(target: T): Ref; +>reactive : Symbol(reactive, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 30, 1)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 26)) +>target : Symbol(target, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 44)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 26)) +>Ref : Symbol(Ref, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 26, 43)) +>T : Symbol(T, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 26)) + +interface ThemeInstance { +>ThemeInstance : Symbol(ThemeInstance, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 63)) + + readonly name: Readonly>; +>name : Symbol(ThemeInstance.name, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 34, 25)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>Ref : Symbol(Ref, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 26, 43)) +} + +declare const ThemeSymbol: InjectionKey; +>ThemeSymbol : Symbol(ThemeSymbol, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 38, 13)) +>InjectionKey : Symbol(InjectionKey, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 24, 1)) +>ThemeInstance : Symbol(ThemeInstance, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 32, 63)) + +declare function inject( +>inject : Symbol(inject, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 38, 55)) + + this: ComponentPublicInstance, +>this : Symbol(this, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 40, 24)) +>ComponentPublicInstance : Symbol(ComponentPublicInstance, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 12, 1)) + + key: InjectionKey | string, +>key : Symbol(key, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 41, 32)) +>InjectionKey : Symbol(InjectionKey, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 24, 1)) + +): any; + +declare const app: App; +>app : Symbol(app, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 45, 13)) +>App : Symbol(App, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 20, 73)) + +app.mixin({ +>app.mixin : Symbol(App.mixin, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 22, 15)) +>app : Symbol(app, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 45, 13)) +>mixin : Symbol(App.mixin, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 22, 15)) + + computed: { +>computed : Symbol(computed, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 46, 11)) + + $vuetify() { +>$vuetify : Symbol($vuetify, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 47, 13)) + + // this is meant to be `any` here + return reactive({ +>reactive : Symbol(reactive, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 30, 1)) + + theme: inject.call(this, ThemeSymbol), +>theme : Symbol(theme, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 50, 23)) +>inject.call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>inject : Symbol(inject, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 38, 55)) +>call : Symbol(CallableFunction.call, Decl(lib.es5.d.ts, --, --)) +>ThemeSymbol : Symbol(ThemeSymbol, Decl(contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts, 38, 13)) + + }); + }, + }, +}); + diff --git a/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.types b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.types new file mode 100644 index 0000000000000..6ba5347f0336f --- /dev/null +++ b/tests/baselines/reference/contextualTypeBasedOnIntersectionWithAnyInTheMix5.types @@ -0,0 +1,148 @@ +//// [tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts] //// + +=== contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts === +type ComputedGetter = (oldValue?: T) => T; +>ComputedGetter : ComputedGetter +> : ^^^^^^^^^^^^^^^^^ +>oldValue : T | undefined +> : ^^^^^^^^^^^^^ + +type ComputedOptions = Record>; +>ComputedOptions : ComputedOptions +> : ^^^^^^^^^^^^^^^ + +type ExtractComputedReturns = { +>ExtractComputedReturns : ExtractComputedReturns +> : ^^^^^^^^^^^^^^^^^^^^^^^^^ + + [key in keyof T]: T[key] extends (...args: any[]) => infer TReturn +>args : any[] +> : ^^^^^ + + ? TReturn + : never; +}; + +interface ComponentOptionsBase { + data?: D; +>data : D | undefined +> : ^^^^^^^^^^^^^ + + computed?: C; +>computed : C | undefined +> : ^^^^^^^^^^^^^ +} + +type ComponentPublicInstance = D & +>ComponentPublicInstance : ComponentPublicInstance +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ExtractComputedReturns; + +type ComponentOptions< +>ComponentOptions : ComponentOptions +> : ^^^^^^^^^^^^^^^^^^^^^^ + + D = any, + C extends ComputedOptions = any, +> = ComponentOptionsBase & ThisType>; + +interface App { + mixin(mixin: ComponentOptions): this; +>mixin : (mixin: ComponentOptions) => this +> : ^ ^^ ^^^^^ +>mixin : ComponentOptions +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +interface InjectionKey extends Symbol {} + +interface Ref { + _v: T; +>_v : T +> : ^ +} + +declare function reactive(target: T): Ref; +>reactive : (target: T) => Ref +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>target : T +> : ^ + +interface ThemeInstance { + readonly name: Readonly>; +>name : Readonly> +> : ^^^^^^^^^^^^^^^^^^^^^ +} + +declare const ThemeSymbol: InjectionKey; +>ThemeSymbol : InjectionKey +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare function inject( +>inject : (this: ComponentPublicInstance, key: InjectionKey | string) => any +> : ^ ^^ ^^ ^^ ^^^^^ + + this: ComponentPublicInstance, +>this : ExtractComputedReturns<{}> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + key: InjectionKey | string, +>key : string | InjectionKey +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +): any; + +declare const app: App; +>app : App +> : ^^^ + +app.mixin({ +>app.mixin({ computed: { $vuetify() { // this is meant to be `any` here return reactive({ theme: inject.call(this, ThemeSymbol), }); }, },}) : App +> : ^^^ +>app.mixin : (mixin: ComponentOptions) => App +> : ^ ^^ ^^^^^^^^ +>app : App +> : ^^^ +>mixin : (mixin: ComponentOptions) => App +> : ^ ^^ ^^^^^^^^ +>{ computed: { $vuetify() { // this is meant to be `any` here return reactive({ theme: inject.call(this, ThemeSymbol), }); }, },} : { computed: { $vuetify(): Ref<{ theme: any; }>; }; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + computed: { +>computed : { $vuetify(): Ref<{ theme: any; }>; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ $vuetify() { // this is meant to be `any` here return reactive({ theme: inject.call(this, ThemeSymbol), }); }, } : { $vuetify(): Ref<{ theme: any; }>; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + $vuetify() { +>$vuetify : () => Ref<{ theme: any; }> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + // this is meant to be `any` here + return reactive({ +>reactive({ theme: inject.call(this, ThemeSymbol), }) : Ref<{ theme: any; }> +> : ^^^^^^^^^^^^^^^^^^^^ +>reactive : (target: T) => Ref +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ theme: inject.call(this, ThemeSymbol), } : { theme: any; } +> : ^^^^^^^^^^^^^^^ + + theme: inject.call(this, ThemeSymbol), +>theme : any +>inject.call(this, ThemeSymbol) : any +>inject.call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ +>inject : (this: ComponentPublicInstance, key: InjectionKey | string) => any +> : ^ ^^ ^^ ^^ ^^^^^ +>call : (this: (this: T, ...args: A) => R, thisArg: T, ...args: A) => R +> : ^ ^^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ +>this : any +>ThemeSymbol : InjectionKey +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + }); + }, + }, +}); + diff --git a/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts new file mode 100644 index 0000000000000..942d7e0a04925 --- /dev/null +++ b/tests/cases/compiler/contextualTypeBasedOnIntersectionWithAnyInTheMix5.ts @@ -0,0 +1,59 @@ +// @strict: true +// @noEmit: true + +type ComputedGetter = (oldValue?: T) => T; +type ComputedOptions = Record>; + +type ExtractComputedReturns = { + [key in keyof T]: T[key] extends (...args: any[]) => infer TReturn + ? TReturn + : never; +}; + +interface ComponentOptionsBase { + data?: D; + computed?: C; +} + +type ComponentPublicInstance = D & + ExtractComputedReturns; + +type ComponentOptions< + D = any, + C extends ComputedOptions = any, +> = ComponentOptionsBase & ThisType>; + +interface App { + mixin(mixin: ComponentOptions): this; +} + +interface InjectionKey extends Symbol {} + +interface Ref { + _v: T; +} + +declare function reactive(target: T): Ref; + +interface ThemeInstance { + readonly name: Readonly>; +} + +declare const ThemeSymbol: InjectionKey; + +declare function inject( + this: ComponentPublicInstance, + key: InjectionKey | string, +): any; + +declare const app: App; +app.mixin({ + computed: { + $vuetify() { + // this is meant to be `any` here + return reactive({ + theme: inject.call(this, ThemeSymbol), + }); + }, + }, +}); From 8645b94cd4fbfff4ce18345acf5f1745c28df752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 5 Aug 2024 18:00:05 +0200 Subject: [PATCH 18/23] small pr feedback --- src/compiler/checker.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 798c85d4916ae..71798a882114d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31577,12 +31577,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).links.type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); } - function isFilteredOutMappedPropertyName(constraint: Type, propertyNameType: Type): boolean { + function isExcludedMappedPropertyName(constraint: Type, propertyNameType: Type): boolean { if (constraint.flags & TypeFlags.Conditional) { return !!(getReducedType(getTrueTypeFromConditionalType(constraint as ConditionalType)).flags & TypeFlags.Never) && isTypeAssignableTo(propertyNameType, (constraint as ConditionalType).extendsType); } if (constraint.flags & TypeFlags.Intersection) { - return some((constraint as IntersectionType).types, t => isFilteredOutMappedPropertyName(t, propertyNameType)); + return some((constraint as IntersectionType).types, t => isExcludedMappedPropertyName(t, propertyNameType)); } return false; } @@ -31620,7 +31620,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (!types) { - return unknownType; + return; } if (types.length === 1) { return types[0]; @@ -31638,15 +31638,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function appendContextualPropertyTypeConsitutent(types: Type[] | undefined, type: Type | undefined) { // any doesn't provide any contextual information but could spoil the overall result by nullifying contextual information provided by other intersection constituents - // at the same time, all types computed based on the contextual information provided by other consistuents are still assignable to any - return isTypeAny(type) ? types : append(types, type); + // so it gets replaced with `unknown` as `T & unknown` is just `T` and all types computed based on the contextual information provided by other consistuents are still assignable to any + return type ? append(types, type.flags & TypeFlags.Any ? unknownType : type) : types; } function getIndexedMappedTypeSubstitutedTypeOfContextualType(type: MappedType, name: __String, nameType: Type | undefined) { const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); const constraint = getConstraintTypeFromMappedType(type); // special case for conditional types pretending to be negated types - if (isFilteredOutMappedPropertyName(constraint, propertyNameType)) { + if (isExcludedMappedPropertyName(constraint, propertyNameType)) { return; } const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; From dac6f7036b44b64163ce32367d533de2bef5da37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 6 Aug 2024 14:37:59 +0200 Subject: [PATCH 19/23] tighten up the check in `isExcludedMappedPropertyName` --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71798a882114d..ee96c477e53f7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31579,7 +31579,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isExcludedMappedPropertyName(constraint: Type, propertyNameType: Type): boolean { if (constraint.flags & TypeFlags.Conditional) { - return !!(getReducedType(getTrueTypeFromConditionalType(constraint as ConditionalType)).flags & TypeFlags.Never) && isTypeAssignableTo(propertyNameType, (constraint as ConditionalType).extendsType); + const type = constraint as ConditionalType; + return !!(getReducedType(getTrueTypeFromConditionalType(type)).flags & TypeFlags.Never) && + isTypeAssignableTo(getFalseTypeFromConditionalType(type), type.checkType) && + isTypeAssignableTo(propertyNameType, type.extendsType); } if (constraint.flags & TypeFlags.Intersection) { return some((constraint as IntersectionType).types, t => isExcludedMappedPropertyName(t, propertyNameType)); From adee09fe97f04713fd9c3c7d37a615ceab0e9f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 6 Aug 2024 17:23:39 +0200 Subject: [PATCH 20/23] address PR feedback --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ee96c477e53f7..161d85c67e991 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31581,7 +31581,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (constraint.flags & TypeFlags.Conditional) { const type = constraint as ConditionalType; return !!(getReducedType(getTrueTypeFromConditionalType(type)).flags & TypeFlags.Never) && - isTypeAssignableTo(getFalseTypeFromConditionalType(type), type.checkType) && + getActualTypeVariable(getFalseTypeFromConditionalType(type)) === getActualTypeVariable(type.checkType) && isTypeAssignableTo(propertyNameType, type.extendsType); } if (constraint.flags & TypeFlags.Intersection) { From e9502f976ec8db0703a6ae9e6e1a25a099a788b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 7 Aug 2024 12:01:27 +0200 Subject: [PATCH 21/23] fixed typo --- src/compiler/checker.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 161d85c67e991..736d1b580e44f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -31602,7 +31602,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isGenericMappedType(constituentType) && !constituentType.declaration.nameType) { const substitutedType = getIndexedMappedTypeSubstitutedTypeOfContextualType(constituentType, name, nameType); - types = appendContextualPropertyTypeConsitutent(types, substitutedType); + types = appendContextualPropertyTypeConstituent(types, substitutedType); continue; } const propertyType = getTypeOfConcretePropertyOfContextualType(constituentType, name); @@ -31614,12 +31614,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } ignoreIndexInfos = true; indexInfoCandidates = undefined; - types = appendContextualPropertyTypeConsitutent(types, propertyType); + types = appendContextualPropertyTypeConstituent(types, propertyType); } if (indexInfoCandidates) { for (const candidate of indexInfoCandidates) { const indexInfoType = getTypeFromIndexInfosOfContextualType(candidate, name, nameType); - types = appendContextualPropertyTypeConsitutent(types, indexInfoType); + types = appendContextualPropertyTypeConstituent(types, indexInfoType); } } if (!types) { @@ -31639,9 +31639,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }, /*noReductions*/ true); } - function appendContextualPropertyTypeConsitutent(types: Type[] | undefined, type: Type | undefined) { + function appendContextualPropertyTypeConstituent(types: Type[] | undefined, type: Type | undefined) { // any doesn't provide any contextual information but could spoil the overall result by nullifying contextual information provided by other intersection constituents - // so it gets replaced with `unknown` as `T & unknown` is just `T` and all types computed based on the contextual information provided by other consistuents are still assignable to any + // so it gets replaced with `unknown` as `T & unknown` is just `T` and all types computed based on the contextual information provided by other constituens are still assignable to any return type ? append(types, type.flags & TypeFlags.Any ? unknownType : type) : types; } From c0e99ae1cc9718f07c0b7c4afea7665bbb5f541c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Mon, 19 Aug 2024 12:20:55 +0200 Subject: [PATCH 22/23] add extra test cases --- ...rtyOfGenericFilteringMappedType.errors.txt | 55 ++++ ...opertyOfGenericFilteringMappedType.symbols | 21 ++ ...PropertyOfGenericFilteringMappedType.types | 41 +++ ...ctionObjectPropertyIntersection.errors.txt | 155 ++++++++++ ...FunctionObjectPropertyIntersection.symbols | 284 +++++++++++++----- ...peFunctionObjectPropertyIntersection.types | 215 ++++++++++++- ...ualPropertyOfGenericFilteringMappedType.ts | 12 + ...lTypeFunctionObjectPropertyIntersection.ts | 49 +++ 8 files changed, 747 insertions(+), 85 deletions(-) create mode 100644 tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.errors.txt create mode 100644 tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt diff --git a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.errors.txt b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.errors.txt new file mode 100644 index 0000000000000..0c45d770b1dad --- /dev/null +++ b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.errors.txt @@ -0,0 +1,55 @@ +contextualPropertyOfGenericFilteringMappedType.ts(38,5): error TS2353: Object literal may only specify known properties, and 'foo' does not exist in type '{ bar: (value: string, prop: "bar") => void; }'. +contextualPropertyOfGenericFilteringMappedType.ts(38,11): error TS7006: Parameter 'value' implicitly has an 'any' type. +contextualPropertyOfGenericFilteringMappedType.ts(38,18): error TS7006: Parameter 'key' implicitly has an 'any' type. + + +==== contextualPropertyOfGenericFilteringMappedType.ts (3 errors) ==== + declare function f1( + data: T, + handlers: { [P in keyof T as P]: (value: T[P], prop: P) => void }, + ): void; + + f1( + { + foo: 0, + bar: "", + }, + { + foo: (value, key) => {}, + bar: (value, key) => {}, + }, + ); + + declare function f2( + data: T, + handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void }, + ): void; + + f2( + { + foo: 0, + bar: "", + }, + { + bar: (value, key) => {}, + }, + ); + + f2( + { + foo: 0, + bar: "", + }, + { + foo: (value, key) => { + ~~~ +!!! error TS2353: Object literal may only specify known properties, and 'foo' does not exist in type '{ bar: (value: string, prop: "bar") => void; }'. + ~~~~~ +!!! error TS7006: Parameter 'value' implicitly has an 'any' type. + ~~~ +!!! error TS7006: Parameter 'key' implicitly has an 'any' type. + // implicit `any`s + }, + }, + ); + \ No newline at end of file diff --git a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols index 5bcaba07ec255..a49b80fcfc9d9 100644 --- a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols +++ b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.symbols @@ -88,3 +88,24 @@ f2( }, ); +f2( +>f2 : Symbol(f2, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 14, 2)) + { + foo: 0, +>foo : Symbol(foo, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 32, 3)) + + bar: "", +>bar : Symbol(bar, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 33, 11)) + + }, + { + foo: (value, key) => { +>foo : Symbol(foo, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 36, 3)) +>value : Symbol(value, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 37, 10)) +>key : Symbol(key, Decl(contextualPropertyOfGenericFilteringMappedType.ts, 37, 16)) + + // implicit `any`s + }, + }, +); + diff --git a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types index b55c98f6f650f..dd7dd68b0f8c8 100644 --- a/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types +++ b/tests/baselines/reference/contextualPropertyOfGenericFilteringMappedType.types @@ -125,3 +125,44 @@ f2( }, ); +f2( +>f2( { foo: 0, bar: "", }, { foo: (value, key) => { // implicit `any`s }, },) : void +> : ^^^^ +>f2 : (data: T, handlers: { [P in keyof T as T[P] extends string ? P : never]: (value: T[P], prop: P) => void; }) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^ ^^^^^ + { +>{ foo: 0, bar: "", } : { foo: number; bar: string; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + foo: 0, +>foo : number +> : ^^^^^^ +>0 : 0 +> : ^ + + bar: "", +>bar : string +> : ^^^^^^ +>"" : "" +> : ^^ + + }, + { +>{ foo: (value, key) => { // implicit `any`s }, } : { foo: (value: any, key: any) => void; } +> : ^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^ + + foo: (value, key) => { +>foo : (value: any, key: any) => void +> : ^ ^^^^^^^ ^^^^^^^^^^^^^^ +>(value, key) => { // implicit `any`s } : (value: any, key: any) => void +> : ^ ^^^^^^^ ^^^^^^^^^^^^^^ +>value : any +> : ^^^ +>key : any +> : ^^^ + + // implicit `any`s + }, + }, +); + diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt new file mode 100644 index 0000000000000..c6927b2005ad0 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.errors.txt @@ -0,0 +1,155 @@ +contextualTypeFunctionObjectPropertyIntersection.ts(84,5): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{ FOO?: Action<{ type: "FOO"; }> | undefined; } & { "*"?: Action<{ type: "FOO"; } | { type: "bar"; }> | undefined; }'. +contextualTypeFunctionObjectPropertyIntersection.ts(84,11): error TS7006: Parameter 'ev' implicitly has an 'any' type. + + +==== contextualTypeFunctionObjectPropertyIntersection.ts (2 errors) ==== + // repro from #48812 + + type Action = (ev: TEvent) => void; + + interface MachineConfig { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"]]?: Action; + } & { + "*"?: Action; + }; + } + + declare function createMachine( + config: MachineConfig + ): void; + + createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + FOO: (ev) => { + ev.type; // should be 'FOO' + }, + }, + }); + + createMachine({ + schema: { + events: {} as { type: "FOO" } | { type: "BAR" }, + }, + on: { + "*": (ev) => { + ev.type; // should be 'FOO' | 'BAR' + }, + }, + }); + + interface MachineConfig2 { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"] as K extends Uppercase ? K : never]?: Action; + } & { + "*"?: Action; + }; + } + + declare function createMachine2( + config: MachineConfig2 + ): void; + + createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + FOO: (ev) => { + ev.type; // should be 'FOO' + }, + }, + }); + + createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + "*": (ev) => { + ev.type; // should be 'FOO' | 'bar' + }, + }, + }); + + createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + bar: (ev) => { + ~~~ +!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{ FOO?: Action<{ type: "FOO"; }> | undefined; } & { "*"?: Action<{ type: "FOO"; } | { type: "bar"; }> | undefined; }'. +!!! related TS6500 contextualTypeFunctionObjectPropertyIntersection.ts:46:3: The expected type comes from property 'on' which is declared here on type 'MachineConfig2<{ type: "FOO"; } | { type: "bar"; }>' + ~~ +!!! error TS7006: Parameter 'ev' implicitly has an 'any' type. + ev // any + }, + }, + }); + + // repro from #49307#issuecomment-1143103607 + + declare function createSlice( + reducers: { [K: string]: (state: string) => void } & { + [K in keyof T]: object; + } + ): void; + + createSlice({ + f(a) {}, + }); + + // repro from #49307#issuecomment-1196014488 + + type Validate = T & { [K in keyof T]: object } + declare function f any>>(s: S, x: Validate): void; + + f(0, { + foo: s => s + 1, + }) + + // repro from 49307#issuecomment-1195858950 + + type SliceCaseReducers = Record State | void>; + + type ValidateSliceCaseReducers> = ACR & { + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any; + } + ? { + prepare(...a: never[]): Omit; + } + : {}; + }; + + declare function createSlice< + State, + CaseReducers extends SliceCaseReducers + >(options: { + initialState: State | (() => State); + reducers: ValidateSliceCaseReducers; + }): void; + + export const clientSlice = createSlice({ + initialState: { + username: "", + isLoggedIn: false, + userId: "", + avatar: "", + }, + reducers: { + onClientUserChanged(state) {}, + }, + }); + + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols index 57db492d04925..1a681fad41bf7 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -103,7 +103,7 @@ createMachine({ >"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 34, 7)) >ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 35, 10)) - ev.type; // should be 'FOO' + ev.type; // should be 'FOO' | 'BAR' >ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 37)) >ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 35, 10)) >type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 32, 37)) @@ -112,159 +112,291 @@ createMachine({ }, }); +interface MachineConfig2 { +>MachineConfig2 : Symbol(MachineConfig2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 41)) + + schema: { +>schema : Symbol(MachineConfig2.schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 59)) + + events: TEvent; +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 42, 11)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) + + }; + on?: { +>on : Symbol(MachineConfig2.on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 4)) + + [K in TEvent["type"] as K extends Uppercase ? K : never]?: Action; +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 46, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 46, 5)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 46, 5)) +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 46, 94)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 46, 5)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) + + } & { + "*"?: Action; +>"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 47, 7)) +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 41, 25)) + + }; +} + +declare function createMachine2( +>createMachine2 : Symbol(createMachine2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 1)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 52, 32)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 52, 48)) + + config: MachineConfig2 +>config : Symbol(config, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 52, 65)) +>MachineConfig2 : Symbol(MachineConfig2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 52, 32)) + +): void; + +createMachine2({ +>createMachine2 : Symbol(createMachine2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 16)) + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 57, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 37)) + + }, + on: { +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 4)) + + FOO: (ev) => { +>FOO : Symbol(FOO, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 61, 10)) + + ev.type; // should be 'FOO' +>ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 19)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 61, 10)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 19)) + + }, + }, +}); + +createMachine2({ +>createMachine2 : Symbol(createMachine2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 16)) + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 37)) + + }, + on: { +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 4)) + + "*": (ev) => { +>"*" : Symbol("*", Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 71, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 72, 10)) + + ev.type; // should be 'FOO' | 'bar' +>ev.type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 37)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 72, 10)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 19), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 69, 37)) + + }, + }, +}); + +createMachine2({ +>createMachine2 : Symbol(createMachine2, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 78, 16)) + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 11)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 19)) +>type : Symbol(type, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 37)) + + }, + on: { +>on : Symbol(on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 81, 4)) + + bar: (ev) => { +>bar : Symbol(bar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 82, 7)) +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 83, 10)) + + ev // any +>ev : Symbol(ev, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 83, 10)) + + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 29)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 122, 2)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 91, 29)) reducers: { [K: string]: (state: string) => void } & { ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 32)) ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 15)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 44, 28)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 91, 32)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 92, 15)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 92, 28)) [K in keyof T]: object; ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 45, 5)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 43, 29)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 93, 5)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 91, 29)) } ): void; createSlice({ ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 122, 2)) f(a) {}, ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 13)) ->a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 50, 4)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 97, 13)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 98, 4)) }); // repro from #49307#issuecomment-1196014488 type Validate = T & { [K in keyof T]: object } ->Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 51, 3)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) ->K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 26)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 14)) +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 99, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 14)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 14)) +>K : Symbol(K, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 26)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 14)) declare function f any>>(s: S, x: Validate): void; ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 49)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 21)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 49)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 19)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 21)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 48)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 67)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 19)) ->x : Symbol(x, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 72)) ->Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 51, 3)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 56, 21)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 48)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 19)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 67)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 19)) +>x : Symbol(x, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 72)) +>Validate : Symbol(Validate, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 99, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 104, 21)) f(0, { ->f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 55, 49)) +>f : Symbol(f, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 103, 49)) foo: s => s + 1, ->foo : Symbol(foo, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 58, 6)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 6)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 59, 6)) +>foo : Symbol(foo, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 106, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 107, 6)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 107, 6)) }) // repro from 49307#issuecomment-1195858950 type SliceCaseReducers = Record State | void>; ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 108, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 23)) >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 48)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 23)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 48)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 23)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 23)) type ValidateSliceCaseReducers> = ACR & { ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 79)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 79)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 33)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 108, 2)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 31)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 33)) [T in keyof ACR]: ACR[T] extends { ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 3)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) ->ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 33)) ->T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 3)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 115, 3)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 33)) +>ACR : Symbol(ACR, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 33)) +>T : Symbol(T, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 115, 3)) reducer(s: S, action?: infer A): any; ->reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 67, 36)) ->s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 12)) ->S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 66, 31)) ->action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 17)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 32)) +>reducer : Symbol(reducer, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 115, 36)) +>s : Symbol(s, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 116, 12)) +>S : Symbol(S, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 114, 31)) +>action : Symbol(action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 116, 17)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 116, 32)) } ? { prepare(...a: never[]): Omit; ->prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 70, 7)) ->a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 71, 16)) +>prepare : Symbol(prepare, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 118, 7)) +>a : Symbol(a, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 119, 16)) >Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) ->A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 32)) +>A : Symbol(A, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 116, 32)) } : {}; }; declare function createSlice< ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 122, 2)) State, ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 124, 29)) CaseReducers extends SliceCaseReducers ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 8)) ->SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 60, 2)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 125, 8)) +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 108, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 124, 29)) >(options: { ->options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 2)) +>options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 127, 2)) initialState: State | (() => State); ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 12)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 127, 12)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 124, 29)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 124, 29)) reducers: ValidateSliceCaseReducers; ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 80, 38)) ->ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 64, 79)) ->State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 29)) ->CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 8)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 128, 38)) +>ValidateSliceCaseReducers : Symbol(ValidateSliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 112, 79)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 124, 29)) +>CaseReducers : Symbol(CaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 125, 8)) }): void; export const clientSlice = createSlice({ ->clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 84, 12)) ->createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 39, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 2)) +>clientSlice : Symbol(clientSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 132, 12)) +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 122, 2)) initialState: { ->initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 84, 40)) +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 132, 40)) username: "", ->username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 85, 17)) +>username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 133, 17)) isLoggedIn: false, ->isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 86, 17)) +>isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 134, 17)) userId: "", ->userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 87, 22)) +>userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 135, 22)) avatar: "", ->avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 88, 15)) +>avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 136, 15)) }, reducers: { ->reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 90, 4)) +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 138, 4)) onClientUserChanged(state) {}, ->onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 91, 13)) ->state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 92, 24)) +>onClientUserChanged : Symbol(onClientUserChanged, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 139, 13)) +>state : Symbol(state, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 140, 24)) }, }); + diff --git a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types index 8f7412b5536e2..02d0173439a01 100644 --- a/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -106,12 +106,12 @@ createMachine({ }); createMachine({ ->createMachine({ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' }, },}) : void -> : ^^^^ +>createMachine({ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' | 'BAR' }, },}) : void +> : ^^^^ >createMachine : (config: MachineConfig) => void > : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ ->{ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' }, },} : { schema: { events: { type: "FOO"; } | { type: "BAR"; }; }; on: { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; }; } -> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ +>{ schema: { events: {} as { type: "FOO" } | { type: "BAR" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' | 'BAR' }, },} : { schema: { events: { type: "FOO"; } | { type: "BAR"; }; }; on: { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ schema: { >schema : { events: { type: "FOO"; } | { type: "BAR"; }; } @@ -135,18 +135,18 @@ createMachine({ on: { >on : { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; } > : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ->{ "*": (ev) => { ev.type; // should be 'FOO' }, } : { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; } -> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>{ "*": (ev) => { ev.type; // should be 'FOO' | 'BAR' }, } : { "*": (ev: { type: "FOO"; } | { type: "BAR"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ "*": (ev) => { >"*" : (ev: { type: "FOO"; } | { type: "BAR"; }) => void > : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ ->(ev) => { ev.type; // should be 'FOO' } : (ev: { type: "FOO"; } | { type: "BAR"; }) => void -> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ +>(ev) => { ev.type; // should be 'FOO' | 'BAR' } : (ev: { type: "FOO"; } | { type: "BAR"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ >ev : { type: "FOO"; } | { type: "BAR"; } > : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ - ev.type; // should be 'FOO' + ev.type; // should be 'FOO' | 'BAR' >ev.type : "FOO" | "BAR" > : ^^^^^^^^^^^^^ >ev : { type: "FOO"; } | { type: "BAR"; } @@ -158,6 +158,202 @@ createMachine({ }, }); +interface MachineConfig2 { +>type : string +> : ^^^^^^ + + schema: { +>schema : { events: TEvent; } +> : ^^^^^^^^^^ ^^^ + + events: TEvent; +>events : TEvent +> : ^^^^^^ + + }; + on?: { +>on : ({ [K in TEvent["type"] as K extends Uppercase ? K : never]?: Action | undefined; } & { "*"?: Action; }) | undefined +> : ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ + + [K in TEvent["type"] as K extends Uppercase ? K : never]?: Action; +>type : K +> : ^ + + } & { + "*"?: Action; +>"*" : Action | undefined +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + }; +} + +declare function createMachine2( +>createMachine2 : (config: MachineConfig2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>type : string +> : ^^^^^^ + + config: MachineConfig2 +>config : MachineConfig2 +> : ^^^^^^^^^^^^^^^^^^^^^^ + +): void; + +createMachine2({ +>createMachine2({ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { FOO: (ev) => { ev.type; // should be 'FOO' }, },}) : void +> : ^^^^ +>createMachine2 : (config: MachineConfig2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { FOO: (ev) => { ev.type; // should be 'FOO' }, },} : { schema: { events: { type: "FOO"; } | { type: "bar"; }; }; on: { FOO: (ev: { type: "FOO"; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as { type: "FOO" } | { type: "bar" }, } : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} as { type: "FOO" } | { type: "bar" } : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ +>type : "FOO" +> : ^^^^^ +>type : "bar" +> : ^^^^^ + + }, + on: { +>on : { FOO: (ev: { type: "FOO"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>{ FOO: (ev) => { ev.type; // should be 'FOO' }, } : { FOO: (ev: { type: "FOO"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + FOO: (ev) => { +>FOO : (ev: { type: "FOO"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^ +>(ev) => { ev.type; // should be 'FOO' } : (ev: { type: "FOO"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^ +>ev : { type: "FOO"; } +> : ^^^^^^^^ ^^^ + + ev.type; // should be 'FOO' +>ev.type : "FOO" +> : ^^^^^ +>ev : { type: "FOO"; } +> : ^^^^^^^^ ^^^ +>type : "FOO" +> : ^^^^^ + + }, + }, +}); + +createMachine2({ +>createMachine2({ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' | 'bar' }, },}) : void +> : ^^^^ +>createMachine2 : (config: MachineConfig2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { "*": (ev) => { ev.type; // should be 'FOO' | 'bar' }, },} : { schema: { events: { type: "FOO"; } | { type: "bar"; }; }; on: { "*": (ev: { type: "FOO"; } | { type: "bar"; }) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as { type: "FOO" } | { type: "bar" }, } : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} as { type: "FOO" } | { type: "bar" } : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ +>type : "FOO" +> : ^^^^^ +>type : "bar" +> : ^^^^^ + + }, + on: { +>on : { "*": (ev: { type: "FOO"; } | { type: "bar"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +>{ "*": (ev) => { ev.type; // should be 'FOO' | 'bar' }, } : { "*": (ev: { type: "FOO"; } | { type: "bar"; }) => void; } +> : ^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + + "*": (ev) => { +>"*" : (ev: { type: "FOO"; } | { type: "bar"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ +>(ev) => { ev.type; // should be 'FOO' | 'bar' } : (ev: { type: "FOO"; } | { type: "bar"; }) => void +> : ^ ^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ +>ev : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ + + ev.type; // should be 'FOO' | 'bar' +>ev.type : "FOO" | "bar" +> : ^^^^^^^^^^^^^ +>ev : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>type : "FOO" | "bar" +> : ^^^^^^^^^^^^^ + + }, + }, +}); + +createMachine2({ +>createMachine2({ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { bar: (ev) => { ev // any }, },}) : void +> : ^^^^ +>createMachine2 : (config: MachineConfig2) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>{ schema: { events: {} as { type: "FOO" } | { type: "bar" }, }, on: { bar: (ev) => { ev // any }, },} : { schema: { events: { type: "FOO"; } | { type: "bar"; }; }; on: { bar: (ev: any) => void; }; } +> : ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ + + schema: { +>schema : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ +>{ events: {} as { type: "FOO" } | { type: "bar" }, } : { events: { type: "FOO"; } | { type: "bar"; }; } +> : ^^^^^^^^^^ ^^^ + + events: {} as { type: "FOO" } | { type: "bar" }, +>events : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} as { type: "FOO" } | { type: "bar" } : { type: "FOO"; } | { type: "bar"; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^ ^^^ +>{} : {} +> : ^^ +>type : "FOO" +> : ^^^^^ +>type : "bar" +> : ^^^^^ + + }, + on: { +>on : { bar: (ev: any) => void; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^^^^ +>{ bar: (ev) => { ev // any }, } : { bar: (ev: any) => void; } +> : ^^^^^^^^ ^^^^^^^^^^^^^^^^^ + + bar: (ev) => { +>bar : (ev: any) => void +> : ^ ^^^^^^^^^^^^^^ +>(ev) => { ev // any } : (ev: any) => void +> : ^ ^^^^^^^^^^^^^^ +>ev : any +> : ^^^ + + ev // any +>ev : any +> : ^^^ + + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( @@ -341,3 +537,4 @@ export const clientSlice = createSlice({ }, }); + diff --git a/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts b/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts index 824a6d554344c..9b540f97206fd 100644 --- a/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts +++ b/tests/cases/compiler/contextualPropertyOfGenericFilteringMappedType.ts @@ -31,3 +31,15 @@ f2( bar: (value, key) => {}, }, ); + +f2( + { + foo: 0, + bar: "", + }, + { + foo: (value, key) => { + // implicit `any`s + }, + }, +); diff --git a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts index b148284f50ba9..661595ea48862 100644 --- a/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -37,11 +37,59 @@ createMachine({ }, on: { "*": (ev) => { + ev.type; // should be 'FOO' | 'BAR' + }, + }, +}); + +interface MachineConfig2 { + schema: { + events: TEvent; + }; + on?: { + [K in TEvent["type"] as K extends Uppercase ? K : never]?: Action; + } & { + "*"?: Action; + }; +} + +declare function createMachine2( + config: MachineConfig2 +): void; + +createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + FOO: (ev) => { ev.type; // should be 'FOO' }, }, }); +createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + "*": (ev) => { + ev.type; // should be 'FOO' | 'bar' + }, + }, +}); + +createMachine2({ + schema: { + events: {} as { type: "FOO" } | { type: "bar" }, + }, + on: { + bar: (ev) => { + ev // any + }, + }, +}); + // repro from #49307#issuecomment-1143103607 declare function createSlice( @@ -96,3 +144,4 @@ export const clientSlice = createSlice({ onClientUserChanged(state) {}, }, }); + 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 23/23] 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; + }, +});