mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Fixed issue with spreading a generic call expression into generic JSX and gather intra expression inference sites from spread expressions (#53444)
This commit is contained in:
parent
04d4580f4e
commit
6947c98929
@ -30106,7 +30106,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return links.immediateTarget;
|
||||
}
|
||||
|
||||
function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type {
|
||||
function checkObjectLiteral(node: ObjectLiteralExpression, checkMode: CheckMode = CheckMode.Normal): Type {
|
||||
const inDestructuringPattern = isAssignmentTarget(node);
|
||||
// Grammar checking
|
||||
checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
|
||||
@ -30208,7 +30208,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
member = prop;
|
||||
allPropertiesTable?.set(prop.escapedName, prop);
|
||||
|
||||
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
|
||||
if (contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
|
||||
(memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) {
|
||||
const inferenceContext = getInferenceContext(node);
|
||||
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
|
||||
@ -30228,7 +30228,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
hasComputedNumberProperty = false;
|
||||
hasComputedSymbolProperty = false;
|
||||
}
|
||||
const type = getReducedType(checkExpression(memberDecl.expression));
|
||||
const type = getReducedType(checkExpression(memberDecl.expression, checkMode & CheckMode.Inferential));
|
||||
if (isValidSpreadType(type)) {
|
||||
const mergedType = tryMergeUnionOfObjectTypeAndEmptyObject(type, inConstContext);
|
||||
if (allPropertiesTable) {
|
||||
@ -30428,7 +30428,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
* @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral,
|
||||
* which also calls getSpreadType.
|
||||
*/
|
||||
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) {
|
||||
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode = CheckMode.Normal) {
|
||||
const attributes = openingLikeElement.attributes;
|
||||
const contextualType = getContextualType(attributes, ContextFlags.None);
|
||||
const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined;
|
||||
@ -30465,7 +30465,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
|
||||
}
|
||||
}
|
||||
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) {
|
||||
if (contextualType && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) {
|
||||
const inferenceContext = getInferenceContext(attributes);
|
||||
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
|
||||
const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!;
|
||||
@ -30478,7 +30478,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
|
||||
attributesTable = createSymbolTable();
|
||||
}
|
||||
const exprType = getReducedType(checkExpressionCached(attributeDecl.expression, checkMode));
|
||||
const exprType = getReducedType(checkExpression(attributeDecl.expression, checkMode & CheckMode.Inferential));
|
||||
if (isTypeAny(exprType)) {
|
||||
hasSpreadAnyType = true;
|
||||
}
|
||||
|
||||
@ -212,4 +212,19 @@ tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInf
|
||||
let test1: "a" = u
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
interface Props<T> {
|
||||
a: (x: string) => T;
|
||||
b: (arg: T) => void;
|
||||
}
|
||||
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
|
||||
Foo({
|
||||
...{
|
||||
a: (x) => 10,
|
||||
b: (arg) => {
|
||||
arg.toString();
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -197,11 +197,37 @@ branch({
|
||||
let test1: "a" = u
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
interface Props<T> {
|
||||
a: (x: string) => T;
|
||||
b: (arg: T) => void;
|
||||
}
|
||||
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
|
||||
Foo({
|
||||
...{
|
||||
a: (x) => 10,
|
||||
b: (arg) => {
|
||||
arg.toString();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
//// [intraExpressionInferences.js]
|
||||
"use strict";
|
||||
// Repros from #47599
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
callIt({
|
||||
produce: function () { return 0; },
|
||||
consume: function (n) { return n.toFixed(); }
|
||||
@ -316,6 +342,12 @@ branch({
|
||||
var test1 = u;
|
||||
}
|
||||
});
|
||||
Foo(__assign({
|
||||
a: function (x) { return 10; },
|
||||
b: function (arg) {
|
||||
arg.toString();
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
//// [intraExpressionInferences.d.ts]
|
||||
@ -383,3 +415,8 @@ declare const branch: <T, U extends T>(_: {
|
||||
then: (u: U) => void;
|
||||
}) => void;
|
||||
declare const x: "a" | "b";
|
||||
interface Props<T> {
|
||||
a: (x: string) => T;
|
||||
b: (arg: T) => void;
|
||||
}
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
|
||||
@ -626,3 +626,45 @@ branch({
|
||||
}
|
||||
})
|
||||
|
||||
interface Props<T> {
|
||||
>Props : Symbol(Props, Decl(intraExpressionInferences.ts, 197, 2))
|
||||
>T : Symbol(T, Decl(intraExpressionInferences.ts, 199, 16))
|
||||
|
||||
a: (x: string) => T;
|
||||
>a : Symbol(Props.a, Decl(intraExpressionInferences.ts, 199, 20))
|
||||
>x : Symbol(x, Decl(intraExpressionInferences.ts, 200, 6))
|
||||
>T : Symbol(T, Decl(intraExpressionInferences.ts, 199, 16))
|
||||
|
||||
b: (arg: T) => void;
|
||||
>b : Symbol(Props.b, Decl(intraExpressionInferences.ts, 200, 22))
|
||||
>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 201, 6))
|
||||
>T : Symbol(T, Decl(intraExpressionInferences.ts, 199, 16))
|
||||
}
|
||||
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
>Foo : Symbol(Foo, Decl(intraExpressionInferences.ts, 202, 1))
|
||||
>T : Symbol(T, Decl(intraExpressionInferences.ts, 204, 21))
|
||||
>props : Symbol(props, Decl(intraExpressionInferences.ts, 204, 24))
|
||||
>Props : Symbol(Props, Decl(intraExpressionInferences.ts, 197, 2))
|
||||
>T : Symbol(T, Decl(intraExpressionInferences.ts, 204, 21))
|
||||
|
||||
Foo({
|
||||
>Foo : Symbol(Foo, Decl(intraExpressionInferences.ts, 202, 1))
|
||||
|
||||
...{
|
||||
a: (x) => 10,
|
||||
>a : Symbol(a, Decl(intraExpressionInferences.ts, 207, 6))
|
||||
>x : Symbol(x, Decl(intraExpressionInferences.ts, 208, 8))
|
||||
|
||||
b: (arg) => {
|
||||
>b : Symbol(b, Decl(intraExpressionInferences.ts, 208, 17))
|
||||
>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 209, 8))
|
||||
|
||||
arg.toString();
|
||||
>arg.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>arg : Symbol(arg, Decl(intraExpressionInferences.ts, 209, 8))
|
||||
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -659,3 +659,45 @@ branch({
|
||||
}
|
||||
})
|
||||
|
||||
interface Props<T> {
|
||||
a: (x: string) => T;
|
||||
>a : (x: string) => T
|
||||
>x : string
|
||||
|
||||
b: (arg: T) => void;
|
||||
>b : (arg: T) => void
|
||||
>arg : T
|
||||
}
|
||||
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
>Foo : <T>(props: Props<T>) => null
|
||||
>props : Props<T>
|
||||
|
||||
Foo({
|
||||
>Foo({ ...{ a: (x) => 10, b: (arg) => { arg.toString(); }, },}) : null
|
||||
>Foo : <T>(props: Props<T>) => null
|
||||
>{ ...{ a: (x) => 10, b: (arg) => { arg.toString(); }, },} : { a: (x: string) => number; b: (arg: number) => void; }
|
||||
|
||||
...{
|
||||
>{ a: (x) => 10, b: (arg) => { arg.toString(); }, } : { a: (x: string) => number; b: (arg: number) => void; }
|
||||
|
||||
a: (x) => 10,
|
||||
>a : (x: string) => number
|
||||
>(x) => 10 : (x: string) => number
|
||||
>x : string
|
||||
>10 : 10
|
||||
|
||||
b: (arg) => {
|
||||
>b : (arg: number) => void
|
||||
>(arg) => { arg.toString(); } : (arg: number) => void
|
||||
>arg : number
|
||||
|
||||
arg.toString();
|
||||
>arg.toString() : string
|
||||
>arg.toString : (radix?: number | undefined) => string
|
||||
>arg : number
|
||||
>toString : (radix?: number | undefined) => string
|
||||
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
=== tests/cases/compiler/jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
// repro #51577
|
||||
|
||||
declare function omit<T, K extends string>(names: readonly K[], obj: T): Omit<T, K>;
|
||||
>omit : Symbol(omit, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 0, 0), Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 84))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 22))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 24))
|
||||
>names : Symbol(names, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 43))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 24))
|
||||
>obj : Symbol(obj, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 63))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 22))
|
||||
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 22))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 24))
|
||||
|
||||
declare function omit<K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>;
|
||||
>omit : Symbol(omit, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 0, 0), Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 84))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 22))
|
||||
>names : Symbol(names, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 40))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 22))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 63))
|
||||
>obj : Symbol(obj, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 66))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 63))
|
||||
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 63))
|
||||
>K : Symbol(K, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 5, 22))
|
||||
|
||||
declare const otherProps: { bar: string, qwe: boolean }
|
||||
>otherProps : Symbol(otherProps, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 13))
|
||||
>bar : Symbol(bar, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 27))
|
||||
>qwe : Symbol(qwe, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 40))
|
||||
|
||||
declare function GenericComponent<T>(props: T): null
|
||||
>GenericComponent : Symbol(GenericComponent, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 55))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 9, 34))
|
||||
>props : Symbol(props, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 9, 37))
|
||||
>T : Symbol(T, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 9, 34))
|
||||
|
||||
<GenericComponent {...omit(['bar'], otherProps)} />; // no error
|
||||
>GenericComponent : Symbol(GenericComponent, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 55))
|
||||
>omit : Symbol(omit, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 0, 0), Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 4, 84))
|
||||
>otherProps : Symbol(otherProps, Decl(jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx, 7, 13))
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
=== tests/cases/compiler/jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
// repro #51577
|
||||
|
||||
declare function omit<T, K extends string>(names: readonly K[], obj: T): Omit<T, K>;
|
||||
>omit : { <T, K extends string>(names: readonly K[], obj: T): Omit<T, K>; <K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>; }
|
||||
>names : readonly K[]
|
||||
>obj : T
|
||||
|
||||
declare function omit<K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>;
|
||||
>omit : { <T, K extends string>(names: readonly K[], obj: T): Omit<T, K>; <K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>; }
|
||||
>names : readonly K[]
|
||||
>obj : T
|
||||
|
||||
declare const otherProps: { bar: string, qwe: boolean }
|
||||
>otherProps : { bar: string; qwe: boolean; }
|
||||
>bar : string
|
||||
>qwe : boolean
|
||||
|
||||
declare function GenericComponent<T>(props: T): null
|
||||
>GenericComponent : <T>(props: T) => null
|
||||
>props : T
|
||||
|
||||
<GenericComponent {...omit(['bar'], otherProps)} />; // no error
|
||||
><GenericComponent {...omit(['bar'], otherProps)} /> : JSX.Element
|
||||
>GenericComponent : <T>(props: T) => null
|
||||
>omit(['bar'], otherProps) : Omit<{ bar: string; qwe: boolean; }, "bar">
|
||||
>omit : { <T, K extends string>(names: readonly K[], obj: T): Omit<T, K>; <K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>; }
|
||||
>['bar'] : "bar"[]
|
||||
>'bar' : "bar"
|
||||
>otherProps : { bar: string; qwe: boolean; }
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
// @jsx: preserve
|
||||
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
// repro #51577
|
||||
|
||||
declare function omit<T, K extends string>(names: readonly K[], obj: T): Omit<T, K>;
|
||||
declare function omit<K extends string>(names: readonly K[]): <T>(obj: T) => Omit<T, K>;
|
||||
|
||||
declare const otherProps: { bar: string, qwe: boolean }
|
||||
|
||||
declare function GenericComponent<T>(props: T): null
|
||||
|
||||
<GenericComponent {...omit(['bar'], otherProps)} />; // no error
|
||||
|
||||
|
||||
@ -199,3 +199,19 @@ branch({
|
||||
let test1: "a" = u
|
||||
}
|
||||
})
|
||||
|
||||
interface Props<T> {
|
||||
a: (x: string) => T;
|
||||
b: (arg: T) => void;
|
||||
}
|
||||
|
||||
declare function Foo<T>(props: Props<T>): null;
|
||||
|
||||
Foo({
|
||||
...{
|
||||
a: (x) => 10,
|
||||
b: (arg) => {
|
||||
arg.toString();
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user