diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4b2378ecba34e..6fce0bdee18c3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30616,29 +30616,65 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { - 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); - } + if (!(t.flags & TypeFlags.StructuredType)) { + return undefined; } - 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; + 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)); + continue; } + const typeOfConcreteProperty = getTypeOfConcretePropertyOfContextualType(t); + if (typeOfConcreteProperty) { + concretePropertyTypes = append(concretePropertyTypes, typeOfConcreteProperty); + continue; + } + applicableIndexInfoCandidates = append(applicableIndexInfoCandidates, t); + } + if (concretePropertyTypes) { + return getIntersectionType(concatenate(concretePropertyTypes, applicableIndexedMappedTypeSubstitions)); + } + const types = concatenate(mapDefined(applicableIndexInfoCandidates, getTypeOfApplicableIndexInfoOfContextualType), applicableIndexedMappedTypeSubstitions); + if (types.length > 0) { + return getIntersectionType(types); } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; + return undefined; } - return undefined; + return isGenericMappedType(t) && !t.declaration.nameType + ? getTypeOfApplicableIndexedMappedTypeSubstitutionOfContextualType(t) + : getTypeOfConcretePropertyOfContextualType(t) || getTypeOfApplicableIndexInfoOfContextualType(t); }, /*noReductions*/ true); + + 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); + } + return undefined; + } + function getTypeOfConcretePropertyOfContextualType(t: Type) { + 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 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/contextualTypeFunctionObjectPropertyIntersection.symbols b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols new file mode 100644 index 0000000000000..be048a5ce37e7 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.symbols @@ -0,0 +1,242 @@ +//// [tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts] //// + +=== contextualTypeFunctionObjectPropertyIntersection.ts === +// repro from #48812 + +type Action = (ev: TEvent) => void; +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>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, 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, 4, 58)) + + events: TEvent; +>events : Symbol(events, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 5, 11)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) + + }; + on?: { +>on : Symbol(MachineConfig.on, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 7, 4)) + + [K in TEvent["type"]]?: Action; +>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, 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, 10, 7)) +>Action : Symbol(Action, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 0, 0)) +>TEvent : Symbol(TEvent, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 4, 24)) + + }; +} + +declare function createMachine( +>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, 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, 13, 1)) + + schema: { +>schema : Symbol(schema, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 19, 15)) + + events: {} as { type: "FOO" } | { type: "BAR" }, +>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, 22, 4)) + + FOO: (ev) => { +>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, 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, 63, 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, 63, 2)) + + f(a) {}, +>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 = Record State | void>; +>SliceCaseReducers : Symbol(SliceCaseReducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 49, 2)) +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 53, 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)) + +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)) + + [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)) + + 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)) + } + ? { + prepare(...a: never[]): Omit; +>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, 57, 32)) + } + : {}; +}; + +declare function createSlice< +>createSlice : Symbol(createSlice, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 28, 3), Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 63, 2)) + + State, +>State : Symbol(State, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 65, 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)) + +>(options: { +>options : Symbol(options, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 68, 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)) + + 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)) + +}): 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)) + + initialState: { +>initialState : Symbol(initialState, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 73, 40)) + + username: "", +>username : Symbol(username, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 74, 17)) + + isLoggedIn: false, +>isLoggedIn : Symbol(isLoggedIn, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 75, 17)) + + userId: "", +>userId : Symbol(userId, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 76, 22)) + + avatar: "", +>avatar : Symbol(avatar, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 77, 15)) + + }, + reducers: { +>reducers : Symbol(reducers, Decl(contextualTypeFunctionObjectPropertyIntersection.ts, 79, 4)) + + onClientUserChanged(state) {}, +>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 new file mode 100644 index 0000000000000..71bb184b425b2 --- /dev/null +++ b/tests/baselines/reference/contextualTypeFunctionObjectPropertyIntersection.types @@ -0,0 +1,206 @@ +//// [tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts] //// + +=== contextualTypeFunctionObjectPropertyIntersection.ts === +// repro from #48812 + +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" + + }, + }, +}); + +// 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) {},}) : void +>createSlice : { (reducers: { [K: string]: (state: string) => void; } & { [K in keyof T]: object; }): void; >(options: { initialState: State | (() => State); reducers: ValidateSliceCaseReducers; }): void; } +>{ f(a) {},} : { f(a: string): void; } + + f(a) {}, +>f : (a: string) => void +>a : string + +}); + +// 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: number) => number; } + + foo: s => s + 1, +>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 = Record State | void>; +>SliceCaseReducers : SliceCaseReducers +>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: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }): 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: { 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: { username: string; isLoggedIn: boolean; userId: string; avatar: string; }) => void +>state : { username: string; isLoggedIn: boolean; userId: string; avatar: string; } + + }, +}); + diff --git a/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols new file mode 100644 index 0000000000000..0d9415509ce8e --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.symbols @@ -0,0 +1,73 @@ +//// [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)) + +) { + 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, 14, 79)) +>T : Symbol(T, Decl(contextuallyTypedJsxAttribute2.tsx, 13, 24)) + + }, +) { + return ; +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +>a : Symbol(JSX.IntrinsicElements.a, Decl(react16.d.ts, 2516, 41)) +} + + {}} />; +>UnwrappedLink2 : Symbol(UnwrappedLink2, Decl(contextuallyTypedJsxAttribute2.tsx, 11, 38)) +>onClick : Symbol(onClick, Decl(contextuallyTypedJsxAttribute2.tsx, 21, 15)) +>e : Symbol(e, Decl(contextuallyTypedJsxAttribute2.tsx, 21, 26)) + + {}} />; +>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 new file mode 100644 index 0000000000000..5fb6754f96150 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedJsxAttribute2.types @@ -0,0 +1,64 @@ +//// [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">) => 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; } + + as?: T; +>as : T | undefined + + }, +) { + return ; +> : JSX.Element +>a : any +>a : any +} + + {}} />; +> {}} /> : 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 +>UnwrappedLink2 : (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/contextualTypeFunctionObjectPropertyIntersection.ts b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts new file mode 100644 index 0000000000000..db09170d13e95 --- /dev/null +++ b/tests/cases/compiler/contextualTypeFunctionObjectPropertyIntersection.ts @@ -0,0 +1,87 @@ +// @strict: true +// @noEmit: true + +// 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) {}, +}); + +// 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) {}, + }, +}); diff --git a/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx new file mode 100644 index 0000000000000..003a44b6d8287 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedJsxAttribute2.tsx @@ -0,0 +1,28 @@ +// @strict: true +// @jsx: react +// @esModuleInterop: true +// @noEmit: true + +/// + +import React from "react"; +import { ComponentPropsWithRef, ElementType } from "react"; + +function UnwrappedLink( + props: Omit, "as">, +) { + return ; +} + + {}} />; + +function UnwrappedLink2( + props: Omit, "as"> & { + as?: T; + }, +) { + return ; +} + + {}} />; + {}} />;