diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 08d81c69e00e6..0e4f940238cd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27596,9 +27596,10 @@ namespace ts { function instantiateContextualType(contextualType: Type | undefined, node: Node, contextFlags: ContextFlags | undefined): Type | undefined { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const inferenceContext = getInferenceContext(node); - // If no inferences have been made, nothing is gained from instantiating as type parameters - // would just be replaced with their defaults similar to the apparent type. - if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidates)) { + // If no inferences have been made, and none of the type parameters for which we are inferring + // specify default types, nothing is gained from instantiating as type parameters would just be + // replaced with their constraints similar to the apparent type. + if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidatesOrDefault)) { // For contextual signatures we incorporate all inferences made so far, e.g. from return // types as well as arguments to the left in a function call. return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper); @@ -35209,6 +35210,10 @@ namespace ts { return !!(info.candidates || info.contraCandidates); } + function hasInferenceCandidatesOrDefault(info: InferenceInfo) { + return !!(info.candidates || info.contraCandidates || hasTypeParameterDefault(info.typeParameter)); + } + function hasOverlappingInferences(a: InferenceInfo[], b: InferenceInfo[]) { for (let i = 0; i < a.length; i++) { if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { diff --git a/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.symbols b/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.symbols new file mode 100644 index 0000000000000..81e0123470ef3 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.symbols @@ -0,0 +1,67 @@ +=== tests/cases/compiler/contextualSignatureConditionalTypeInstantiationUsingDefault.ts === +// repro #46310 + +export interface TypegenDisabled { +>TypegenDisabled : Symbol(TypegenDisabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 0, 0)) + + "@@xstate/typegen": false; +>"@@xstate/typegen" : Symbol(TypegenDisabled["@@xstate/typegen"], Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 2, 34)) +} +export interface TypegenEnabled { +>TypegenEnabled : Symbol(TypegenEnabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 4, 1)) + + "@@xstate/typegen": true; +>"@@xstate/typegen" : Symbol(TypegenEnabled["@@xstate/typegen"], Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 5, 33)) +} + +type ActionFunction = (event: TEvent) => void; +>ActionFunction : Symbol(ActionFunction, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 7, 1)) +>TEvent : Symbol(TEvent, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 20)) +>type : Symbol(type, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 36)) +>event : Symbol(event, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 56)) +>TEvent : Symbol(TEvent, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 20)) + +declare function createMachine< +>createMachine : Symbol(createMachine, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 79)) + + TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled +>TTypesMeta : Symbol(TTypesMeta, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 11, 31)) +>TypegenEnabled : Symbol(TypegenEnabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 4, 1)) +>TypegenDisabled : Symbol(TypegenDisabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 0, 0)) +>TypegenDisabled : Symbol(TypegenDisabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 0, 0)) + +>( + config: { +>config : Symbol(config, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 13, 2)) + + types?: TTypesMeta; +>types : Symbol(types, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 14, 11)) +>TTypesMeta : Symbol(TTypesMeta, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 11, 31)) + + }, + implementations: TTypesMeta extends TypegenEnabled +>implementations : Symbol(implementations, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 16, 4)) +>TTypesMeta : Symbol(TTypesMeta, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 11, 31)) +>TypegenEnabled : Symbol(TypegenEnabled, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 4, 1)) + + ? ActionFunction<{ type: "test" }> +>ActionFunction : Symbol(ActionFunction, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 7, 1)) +>type : Symbol(type, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 18, 22)) + + : ActionFunction<{ type: string }> +>ActionFunction : Symbol(ActionFunction, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 7, 1)) +>type : Symbol(type, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 19, 22)) + +): void; + +createMachine({}, (ev) => { +>createMachine : Symbol(createMachine, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 9, 79)) +>ev : Symbol(ev, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 22, 19)) + + ev.type; // should be `string` +>ev.type : Symbol(type, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 19, 22)) +>ev : Symbol(ev, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 22, 19)) +>type : Symbol(type, Decl(contextualSignatureConditionalTypeInstantiationUsingDefault.ts, 19, 22)) + +}); + diff --git a/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.types b/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.types new file mode 100644 index 0000000000000..b98593ef5bd56 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureConditionalTypeInstantiationUsingDefault.types @@ -0,0 +1,56 @@ +=== tests/cases/compiler/contextualSignatureConditionalTypeInstantiationUsingDefault.ts === +// repro #46310 + +export interface TypegenDisabled { + "@@xstate/typegen": false; +>"@@xstate/typegen" : false +>false : false +} +export interface TypegenEnabled { + "@@xstate/typegen": true; +>"@@xstate/typegen" : true +>true : true +} + +type ActionFunction = (event: TEvent) => void; +>ActionFunction : ActionFunction +>type : string +>event : TEvent + +declare function createMachine< +>createMachine : (config: { types?: TTypesMeta;}, implementations: TTypesMeta extends TypegenEnabled ? ActionFunction<{ type: "test";}> : ActionFunction<{ type: string;}>) => void + + TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled +>( + config: { +>config : { types?: TTypesMeta | undefined; } + + types?: TTypesMeta; +>types : TTypesMeta | undefined + + }, + implementations: TTypesMeta extends TypegenEnabled +>implementations : TTypesMeta extends TypegenEnabled ? ActionFunction<{ type: "test"; }> : ActionFunction<{ type: string; }> + + ? ActionFunction<{ type: "test" }> +>type : "test" + + : ActionFunction<{ type: string }> +>type : string + +): void; + +createMachine({}, (ev) => { +>createMachine({}, (ev) => { ev.type; // should be `string`}) : void +>createMachine : (config: { types?: TTypesMeta | undefined; }, implementations: TTypesMeta extends TypegenEnabled ? ActionFunction<{ type: "test"; }> : ActionFunction<{ type: string; }>) => void +>{} : {} +>(ev) => { ev.type; // should be `string`} : (ev: { type: string; }) => void +>ev : { type: string; } + + ev.type; // should be `string` +>ev.type : string +>ev : { type: string; } +>type : string + +}); + diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameter.js b/tests/baselines/reference/genericInferenceDefaultTypeParameter.js new file mode 100644 index 0000000000000..3e57419215cc1 --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameter.js @@ -0,0 +1,21 @@ +//// [genericInferenceDefaultTypeParameter.ts] +// Repro from #50858 + +type Type = { + a: (e: string) => void; + b: (e: number) => void; +} + +declare function f1(props: Type[T]): void; + +f1(event => { }); +f1<"a">(event => { }); +f1<"b">(event => { }); + + +//// [genericInferenceDefaultTypeParameter.js] +"use strict"; +// Repro from #50858 +f1(function (event) { }); +f1(function (event) { }); +f1(function (event) { }); diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameter.symbols b/tests/baselines/reference/genericInferenceDefaultTypeParameter.symbols new file mode 100644 index 0000000000000..999ca147ac770 --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameter.symbols @@ -0,0 +1,35 @@ +=== tests/cases/compiler/genericInferenceDefaultTypeParameter.ts === +// Repro from #50858 + +type Type = { +>Type : Symbol(Type, Decl(genericInferenceDefaultTypeParameter.ts, 0, 0)) + + a: (e: string) => void; +>a : Symbol(a, Decl(genericInferenceDefaultTypeParameter.ts, 2, 13)) +>e : Symbol(e, Decl(genericInferenceDefaultTypeParameter.ts, 3, 8)) + + b: (e: number) => void; +>b : Symbol(b, Decl(genericInferenceDefaultTypeParameter.ts, 3, 27)) +>e : Symbol(e, Decl(genericInferenceDefaultTypeParameter.ts, 4, 8)) +} + +declare function f1(props: Type[T]): void; +>f1 : Symbol(f1, Decl(genericInferenceDefaultTypeParameter.ts, 5, 1)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameter.ts, 7, 20)) +>Type : Symbol(Type, Decl(genericInferenceDefaultTypeParameter.ts, 0, 0)) +>props : Symbol(props, Decl(genericInferenceDefaultTypeParameter.ts, 7, 48)) +>Type : Symbol(Type, Decl(genericInferenceDefaultTypeParameter.ts, 0, 0)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameter.ts, 7, 20)) + +f1(event => { }); +>f1 : Symbol(f1, Decl(genericInferenceDefaultTypeParameter.ts, 5, 1)) +>event : Symbol(event, Decl(genericInferenceDefaultTypeParameter.ts, 9, 3)) + +f1<"a">(event => { }); +>f1 : Symbol(f1, Decl(genericInferenceDefaultTypeParameter.ts, 5, 1)) +>event : Symbol(event, Decl(genericInferenceDefaultTypeParameter.ts, 10, 8)) + +f1<"b">(event => { }); +>f1 : Symbol(f1, Decl(genericInferenceDefaultTypeParameter.ts, 5, 1)) +>event : Symbol(event, Decl(genericInferenceDefaultTypeParameter.ts, 11, 8)) + diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameter.types b/tests/baselines/reference/genericInferenceDefaultTypeParameter.types new file mode 100644 index 0000000000000..9b35a11dc4228 --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameter.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/genericInferenceDefaultTypeParameter.ts === +// Repro from #50858 + +type Type = { +>Type : { a: (e: string) => void; b: (e: number) => void; } + + a: (e: string) => void; +>a : (e: string) => void +>e : string + + b: (e: number) => void; +>b : (e: number) => void +>e : number +} + +declare function f1(props: Type[T]): void; +>f1 : (props: Type[T]) => void +>props : Type[T] + +f1(event => { }); +>f1(event => { }) : void +>f1 : (props: Type[T]) => void +>event => { } : (event: string) => void +>event : string + +f1<"a">(event => { }); +>f1<"a">(event => { }) : void +>f1 : (props: Type[T]) => void +>event => { } : (event: string) => void +>event : string + +f1<"b">(event => { }); +>f1<"b">(event => { }) : void +>f1 : (props: Type[T]) => void +>event => { } : (event: number) => void +>event : number + diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.js b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.js new file mode 100644 index 0000000000000..011c8b4d995f8 --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.js @@ -0,0 +1,29 @@ +//// [genericInferenceDefaultTypeParameterJsxReact.tsx] +/// + +// Repro from #50858 + +import React, { ComponentPropsWithRef, ElementType, ReactNode } from 'react'; + +type ButtonBaseProps = ComponentPropsWithRef & { children?: ReactNode }; + +function Component(props: ButtonBaseProps) { + return <>; +} + +const v1 = e.preventDefault()} />; + + +//// [genericInferenceDefaultTypeParameterJsxReact.js] +"use strict"; +/// +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +exports.__esModule = true; +// Repro from #50858 +var react_1 = __importDefault(require("react")); +function Component(props) { + return react_1["default"].createElement(react_1["default"].Fragment, null); +} +var v1 = react_1["default"].createElement(Component, { onClick: function (e) { return e.preventDefault(); } }); diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.symbols b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.symbols new file mode 100644 index 0000000000000..e5fff8879efc8 --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.symbols @@ -0,0 +1,40 @@ +=== tests/cases/compiler/genericInferenceDefaultTypeParameterJsxReact.tsx === +/// + +// Repro from #50858 + +import React, { ComponentPropsWithRef, ElementType, ReactNode } from 'react'; +>React : Symbol(React, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 6)) +>ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 15)) +>ElementType : Symbol(ElementType, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 38)) +>ReactNode : Symbol(ReactNode, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 51)) + +type ButtonBaseProps = ComponentPropsWithRef & { children?: ReactNode }; +>ButtonBaseProps : Symbol(ButtonBaseProps, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 77)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 6, 21)) +>ElementType : Symbol(ElementType, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 38)) +>ComponentPropsWithRef : Symbol(ComponentPropsWithRef, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 15)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 6, 21)) +>children : Symbol(children, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 6, 74)) +>ReactNode : Symbol(ReactNode, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 51)) + +function Component(props: ButtonBaseProps) { +>Component : Symbol(Component, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 6, 98)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 8, 19)) +>ElementType : Symbol(ElementType, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 38)) +>props : Symbol(props, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 8, 51)) +>ButtonBaseProps : Symbol(ButtonBaseProps, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 4, 77)) +>T : Symbol(T, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 8, 19)) + + return <>; +} + +const v1 = e.preventDefault()} />; +>v1 : Symbol(v1, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 12, 5)) +>Component : Symbol(Component, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 6, 98)) +>onClick : Symbol(onClick, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 12, 21)) +>e : Symbol(e, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 12, 31)) +>e.preventDefault : Symbol(React.SyntheticEvent.preventDefault, Decl(react16.d.ts, 642, 31)) +>e : Symbol(e, Decl(genericInferenceDefaultTypeParameterJsxReact.tsx, 12, 31)) +>preventDefault : Symbol(React.SyntheticEvent.preventDefault, Decl(react16.d.ts, 642, 31)) + diff --git a/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.types b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.types new file mode 100644 index 0000000000000..357408d93bdde --- /dev/null +++ b/tests/baselines/reference/genericInferenceDefaultTypeParameterJsxReact.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/genericInferenceDefaultTypeParameterJsxReact.tsx === +/// + +// Repro from #50858 + +import React, { ComponentPropsWithRef, ElementType, ReactNode } from 'react'; +>React : typeof React +>ComponentPropsWithRef : any +>ElementType : any +>ReactNode : any + +type ButtonBaseProps = ComponentPropsWithRef & { children?: ReactNode }; +>ButtonBaseProps : ButtonBaseProps +>children : React.ReactNode + +function Component(props: ButtonBaseProps) { +>Component : = "span">(props: ButtonBaseProps) => JSX.Element +>props : ButtonBaseProps + + return <>; +><> : JSX.Element +} + +const v1 = e.preventDefault()} />; +>v1 : JSX.Element +> e.preventDefault()} /> : JSX.Element +>Component : = "span">(props: ButtonBaseProps) => JSX.Element +>onClick : (e: React.MouseEvent) => void +>e => e.preventDefault() : (e: React.MouseEvent) => void +>e : React.MouseEvent +>e.preventDefault() : void +>e.preventDefault : () => void +>e : React.MouseEvent +>preventDefault : () => void + diff --git a/tests/cases/compiler/contextualSignatureConditionalTypeInstantiationUsingDefault.ts b/tests/cases/compiler/contextualSignatureConditionalTypeInstantiationUsingDefault.ts new file mode 100644 index 0000000000000..01949742f7a83 --- /dev/null +++ b/tests/cases/compiler/contextualSignatureConditionalTypeInstantiationUsingDefault.ts @@ -0,0 +1,28 @@ +// @strict: true +// @noEmit: true + +// repro #46310 + +export interface TypegenDisabled { + "@@xstate/typegen": false; +} +export interface TypegenEnabled { + "@@xstate/typegen": true; +} + +type ActionFunction = (event: TEvent) => void; + +declare function createMachine< + TTypesMeta extends TypegenEnabled | TypegenDisabled = TypegenDisabled +>( + config: { + types?: TTypesMeta; + }, + implementations: TTypesMeta extends TypegenEnabled + ? ActionFunction<{ type: "test" }> + : ActionFunction<{ type: string }> +): void; + +createMachine({}, (ev) => { + ev.type; // should be `string` +}); diff --git a/tests/cases/compiler/genericInferenceDefaultTypeParameter.ts b/tests/cases/compiler/genericInferenceDefaultTypeParameter.ts new file mode 100644 index 0000000000000..85ffe971b009a --- /dev/null +++ b/tests/cases/compiler/genericInferenceDefaultTypeParameter.ts @@ -0,0 +1,14 @@ +// @strict: true + +// Repro from #50858 + +type Type = { + a: (e: string) => void; + b: (e: number) => void; +} + +declare function f1(props: Type[T]): void; + +f1(event => { }); +f1<"a">(event => { }); +f1<"b">(event => { }); diff --git a/tests/cases/compiler/genericInferenceDefaultTypeParameterJsxReact.tsx b/tests/cases/compiler/genericInferenceDefaultTypeParameterJsxReact.tsx new file mode 100644 index 0000000000000..13b7bc8642155 --- /dev/null +++ b/tests/cases/compiler/genericInferenceDefaultTypeParameterJsxReact.tsx @@ -0,0 +1,17 @@ +// @strict: true +// @esModuleInterop: true +// @jsx: react + +/// + +// Repro from #50858 + +import React, { ComponentPropsWithRef, ElementType, ReactNode } from 'react'; + +type ButtonBaseProps = ComponentPropsWithRef & { children?: ReactNode }; + +function Component(props: ButtonBaseProps) { + return <>; +} + +const v1 = e.preventDefault()} />;