Skip to content

Commit ee546fb

Browse files
authored
Merge pull request #22764 from Microsoft/fixInferTypeDeclarationFiles
Fix missing 'infer T' in declaration files
2 parents c930895 + 275311e commit ee546fb

File tree

11 files changed

+443
-245
lines changed

11 files changed

+443
-245
lines changed

src/compiler/binder.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ namespace ts {
101101
HasLocals = 1 << 5,
102102
IsInterface = 1 << 6,
103103
IsObjectLiteralOrClassExpressionMethod = 1 << 7,
104-
IsInferenceContainer = 1 << 8,
105104
}
106105

107106
const binder = createBinder();
@@ -121,7 +120,6 @@ namespace ts {
121120
let container: Node;
122121
let containerContainer: Node; // Container one level up
123122
let blockScopeContainer: Node;
124-
let inferenceContainer: Node;
125123
let lastContainer: Node;
126124
let seenThisKeyword: boolean;
127125

@@ -190,7 +188,6 @@ namespace ts {
190188
container = undefined;
191189
containerContainer = undefined;
192190
blockScopeContainer = undefined;
193-
inferenceContainer = undefined;
194191
lastContainer = undefined;
195192
seenThisKeyword = false;
196193
currentFlow = undefined;
@@ -569,13 +566,6 @@ namespace ts {
569566
bindChildren(node);
570567
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
571568
}
572-
else if (containerFlags & ContainerFlags.IsInferenceContainer) {
573-
const saveInferenceContainer = inferenceContainer;
574-
inferenceContainer = node;
575-
node.locals = undefined;
576-
bindChildren(node);
577-
inferenceContainer = saveInferenceContainer;
578-
}
579569
else {
580570
bindChildren(node);
581571
}
@@ -1434,9 +1424,6 @@ namespace ts {
14341424
case SyntaxKind.MappedType:
14351425
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
14361426

1437-
case SyntaxKind.ConditionalType:
1438-
return ContainerFlags.IsInferenceContainer;
1439-
14401427
case SyntaxKind.SourceFile:
14411428
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals;
14421429

@@ -2638,13 +2625,25 @@ namespace ts {
26382625
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
26392626
}
26402627

2628+
function getInferTypeContainer(node: Node): ConditionalTypeNode {
2629+
while (node) {
2630+
const parent = node.parent;
2631+
if (parent && parent.kind === SyntaxKind.ConditionalType && (<ConditionalTypeNode>parent).extendsType === node) {
2632+
return <ConditionalTypeNode>parent;
2633+
}
2634+
node = parent;
2635+
}
2636+
return undefined;
2637+
}
2638+
26412639
function bindTypeParameter(node: TypeParameterDeclaration) {
26422640
if (node.parent.kind === SyntaxKind.InferType) {
2643-
if (inferenceContainer) {
2644-
if (!inferenceContainer.locals) {
2645-
inferenceContainer.locals = createSymbolTable();
2641+
const container = getInferTypeContainer(node.parent);
2642+
if (container) {
2643+
if (!container.locals) {
2644+
container.locals = createSymbolTable();
26462645
}
2647-
declareSymbol(inferenceContainer.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
2646+
declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
26482647
}
26492648
else {
26502649
bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node));

src/compiler/checker.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2895,7 +2895,8 @@ namespace ts {
28952895
flags,
28962896
tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: noop },
28972897
encounteredError: false,
2898-
symbolStack: undefined
2898+
symbolStack: undefined,
2899+
inferTypeParameters: undefined
28992900
};
29002901
}
29012902

@@ -2987,6 +2988,9 @@ namespace ts {
29872988
return typeReferenceToTypeNode(<TypeReference>type);
29882989
}
29892990
if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) {
2991+
if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) {
2992+
return createInferTypeNode(createTypeParameterDeclaration(getNameOfSymbolAsWritten(type.symbol)));
2993+
}
29902994
const name = type.symbol ? symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ false) : createIdentifier("?");
29912995
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
29922996
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
@@ -3027,7 +3031,10 @@ namespace ts {
30273031
}
30283032
if (type.flags & TypeFlags.Conditional) {
30293033
const checkTypeNode = typeToTypeNodeHelper((<ConditionalType>type).checkType, context);
3034+
const saveInferTypeParameters = context.inferTypeParameters;
3035+
context.inferTypeParameters = (<ConditionalType>type).root.inferTypeParameters;
30303036
const extendsTypeNode = typeToTypeNodeHelper((<ConditionalType>type).extendsType, context);
3037+
context.inferTypeParameters = saveInferTypeParameters;
30313038
const trueTypeNode = typeToTypeNodeHelper(getTrueTypeFromConditionalType(<ConditionalType>type), context);
30323039
const falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(<ConditionalType>type), context);
30333040
return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
@@ -3692,6 +3699,7 @@ namespace ts {
36923699
// State
36933700
encounteredError: boolean;
36943701
symbolStack: Symbol[] | undefined;
3702+
inferTypeParameters: TypeParameter[] | undefined;
36953703
}
36963704

36973705
function isDefaultBindingContext(location: Node) {

tests/baselines/reference/inferTypes1.errors.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(75,15): error TS2304: C
1515
tests/cases/conformance/types/conditional/inferTypes1.ts(75,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
1616
tests/cases/conformance/types/conditional/inferTypes1.ts(75,43): error TS2304: Cannot find name 'U'.
1717
tests/cases/conformance/types/conditional/inferTypes1.ts(75,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
18-
tests/cases/conformance/types/conditional/inferTypes1.ts(81,44): error TS2344: Type 'U' does not satisfy the constraint 'string'.
18+
tests/cases/conformance/types/conditional/inferTypes1.ts(82,44): error TS2344: Type 'U' does not satisfy the constraint 'string'.
1919
Type 'number' is not assignable to type 'string'.
20-
tests/cases/conformance/types/conditional/inferTypes1.ts(143,40): error TS2322: Type 'T' is not assignable to type 'string'.
20+
tests/cases/conformance/types/conditional/inferTypes1.ts(144,40): error TS2322: Type 'T' is not assignable to type 'string'.
2121

2222

2323
==== tests/cases/conformance/types/conditional/inferTypes1.ts (16 errors) ====
@@ -127,6 +127,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(143,40): error TS2322:
127127
!!! error TS2304: Cannot find name 'U'.
128128
~
129129
!!! error TS4081: Exported type alias 'T62' has or is using private name 'U'.
130+
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
130131

131132
type T70<T extends string> = { x: T };
132133
type T71<T> = T extends T70<infer U> ? T70<U> : never;

tests/baselines/reference/inferTypes1.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type T54 = X3<{ a: (x: number) => void, b: () => void }>; // number
7474
type T60 = infer U; // Error
7575
type T61<T> = infer A extends infer B ? infer C : infer D; // Error
7676
type T62<T> = U extends (infer U)[] ? U : U; // Error
77+
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
7778

7879
type T70<T extends string> = { x: T };
7980
type T71<T> = T extends T70<infer U> ? T70<U> : never;

0 commit comments

Comments
 (0)