Skip to content

Commit 7714a2b

Browse files
authored
Merge pull request #22989 from Microsoft/fixImpliedConstraint
Fix implied constraints in conditional types
2 parents b47c1fd + f1bb530 commit 7714a2b

File tree

6 files changed

+180
-6
lines changed

6 files changed

+180
-6
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7407,7 +7407,7 @@ namespace ts {
74077407

74087408
function getConstrainedTypeVariable(typeVariable: TypeVariable, node: Node) {
74097409
let constraints: Type[];
7410-
while (isPartOfTypeNode(node)) {
7410+
while (node && !isStatement(node)) {
74117411
const parent = node.parent;
74127412
if (parent.kind === SyntaxKind.ConditionalType && node === (<ConditionalTypeNode>parent).trueType) {
74137413
const constraint = getImpliedConstraint(typeVariable, (<ConditionalTypeNode>parent).checkType, (<ConditionalTypeNode>parent).extendsType);
@@ -8356,17 +8356,17 @@ namespace ts {
83568356
// resolution of the conditional type such that a later instantiation will properly distribute
83578357
// over union types.
83588358
const isDeferred = root.isDistributive && maybeTypeOfKind(checkType, TypeFlags.Instantiable);
8359-
let combinedMapper: TypeMapper;
8360-
if (root.inferTypeParameters) {
8361-
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
8359+
let combinedMapper: TypeMapper;
8360+
if (root.inferTypeParameters) {
8361+
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
83628362
if (!isDeferred) {
83638363
// We don't want inferences from constraints as they may cause us to eagerly resolve the
83648364
// conditional type instead of deferring resolution. Also, we always want strict function
83658365
// types rules (i.e. proper contravariance) for inferences.
83668366
inferTypes(context.inferences, checkType, extendsType, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict);
83678367
}
8368-
combinedMapper = combineTypeMappers(mapper, context);
8369-
}
8368+
combinedMapper = combineTypeMappers(mapper, context);
8369+
}
83708370
if (!isDeferred) {
83718371
// Return union of trueType and falseType for 'any' since it matches anything
83728372
if (checkType.flags & TypeFlags.Any) {

tests/baselines/reference/conditionalTypes1.errors.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,4 +501,16 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS
501501
type Extracted<Struct> = {
502502
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
503503
}
504+
505+
// Repro from #22985
506+
507+
type RecursivePartial<T> = {
508+
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
509+
T[P] extends object ? RecursivePartial<T[P]> : T[P];
510+
};
511+
512+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
513+
514+
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
515+
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
504516

tests/baselines/reference/conditionalTypes1.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,18 @@ declare interface ExtractFooBar<FB extends FooBar> { }
339339
type Extracted<Struct> = {
340340
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
341341
}
342+
343+
// Repro from #22985
344+
345+
type RecursivePartial<T> = {
346+
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
347+
T[P] extends object ? RecursivePartial<T[P]> : T[P];
348+
};
349+
350+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
351+
352+
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
353+
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
342354

343355

344356
//// [conditionalTypes1.js]
@@ -435,6 +447,8 @@ var f45 = function (value) { return value; }; // Error
435447
// Repro from #21863
436448
function f50() {
437449
}
450+
var a = { o: 1, b: 2, c: [{ a: 1, c: '213' }] };
451+
assign(a, { o: 2, c: { 0: { a: 2, c: '213123' } } });
438452

439453

440454
//// [conditionalTypes1.d.ts]
@@ -687,3 +701,17 @@ declare interface ExtractFooBar<FB extends FooBar> {
687701
declare type Extracted<Struct> = {
688702
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
689703
};
704+
declare type RecursivePartial<T> = {
705+
[P in keyof T]?: T[P] extends Array<any> ? {
706+
[index: number]: RecursivePartial<T[P][0]>;
707+
} : T[P] extends object ? RecursivePartial<T[P]> : T[P];
708+
};
709+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
710+
declare var a: {
711+
o: number;
712+
b: number;
713+
c: {
714+
a: number;
715+
c: string;
716+
}[];
717+
};

tests/baselines/reference/conditionalTypes1.symbols

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,3 +1317,57 @@ type Extracted<Struct> = {
13171317
>K : Symbol(K, Decl(conditionalTypes1.ts, 338, 5))
13181318
}
13191319

1320+
// Repro from #22985
1321+
1322+
type RecursivePartial<T> = {
1323+
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
1324+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1325+
1326+
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
1327+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1328+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1329+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1330+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1331+
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
1332+
>index : Symbol(index, Decl(conditionalTypes1.ts, 344, 47))
1333+
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
1334+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1335+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1336+
1337+
T[P] extends object ? RecursivePartial<T[P]> : T[P];
1338+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1339+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1340+
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
1341+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1342+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1343+
>T : Symbol(T, Decl(conditionalTypes1.ts, 343, 22))
1344+
>P : Symbol(P, Decl(conditionalTypes1.ts, 344, 3))
1345+
1346+
};
1347+
1348+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
1349+
>assign : Symbol(assign, Decl(conditionalTypes1.ts, 346, 2))
1350+
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
1351+
>o : Symbol(o, Decl(conditionalTypes1.ts, 348, 27))
1352+
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
1353+
>a : Symbol(a, Decl(conditionalTypes1.ts, 348, 32))
1354+
>RecursivePartial : Symbol(RecursivePartial, Decl(conditionalTypes1.ts, 339, 1))
1355+
>T : Symbol(T, Decl(conditionalTypes1.ts, 348, 24))
1356+
1357+
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
1358+
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 3))
1359+
>o : Symbol(o, Decl(conditionalTypes1.ts, 350, 9))
1360+
>b : Symbol(b, Decl(conditionalTypes1.ts, 350, 14))
1361+
>c : Symbol(c, Decl(conditionalTypes1.ts, 350, 20))
1362+
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 26))
1363+
>c : Symbol(c, Decl(conditionalTypes1.ts, 350, 31))
1364+
1365+
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
1366+
>assign : Symbol(assign, Decl(conditionalTypes1.ts, 346, 2))
1367+
>a : Symbol(a, Decl(conditionalTypes1.ts, 350, 3))
1368+
>o : Symbol(o, Decl(conditionalTypes1.ts, 351, 11))
1369+
>c : Symbol(c, Decl(conditionalTypes1.ts, 351, 16))
1370+
>0 : Symbol(0, Decl(conditionalTypes1.ts, 351, 21))
1371+
>a : Symbol(a, Decl(conditionalTypes1.ts, 351, 25))
1372+
>c : Symbol(c, Decl(conditionalTypes1.ts, 351, 30))
1373+

tests/baselines/reference/conditionalTypes1.types

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,3 +1474,71 @@ type Extracted<Struct> = {
14741474
>K : K
14751475
}
14761476

1477+
// Repro from #22985
1478+
1479+
type RecursivePartial<T> = {
1480+
>RecursivePartial : RecursivePartial<T>
1481+
>T : T
1482+
1483+
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
1484+
>P : P
1485+
>T : T
1486+
>T : T
1487+
>P : P
1488+
>Array : T[]
1489+
>index : number
1490+
>RecursivePartial : RecursivePartial<T>
1491+
>T : T
1492+
>P : P
1493+
1494+
T[P] extends object ? RecursivePartial<T[P]> : T[P];
1495+
>T : T
1496+
>P : P
1497+
>RecursivePartial : RecursivePartial<T>
1498+
>T : T
1499+
>P : P
1500+
>T : T
1501+
>P : P
1502+
1503+
};
1504+
1505+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
1506+
>assign : <T>(o: T, a: RecursivePartial<T>) => void
1507+
>T : T
1508+
>o : T
1509+
>T : T
1510+
>a : RecursivePartial<T>
1511+
>RecursivePartial : RecursivePartial<T>
1512+
>T : T
1513+
1514+
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
1515+
>a : { o: number; b: number; c: { a: number; c: string; }[]; }
1516+
>{o: 1, b: 2, c: [{a: 1, c: '213'}]} : { o: number; b: number; c: { a: number; c: string; }[]; }
1517+
>o : number
1518+
>1 : 1
1519+
>b : number
1520+
>2 : 2
1521+
>c : { a: number; c: string; }[]
1522+
>[{a: 1, c: '213'}] : { a: number; c: string; }[]
1523+
>{a: 1, c: '213'} : { a: number; c: string; }
1524+
>a : number
1525+
>1 : 1
1526+
>c : string
1527+
>'213' : "213"
1528+
1529+
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
1530+
>assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) : void
1531+
>assign : <T>(o: T, a: RecursivePartial<T>) => void
1532+
>a : { o: number; b: number; c: { a: number; c: string; }[]; }
1533+
>{o: 2, c: {0: {a: 2, c: '213123'}}} : { o: number; c: { 0: { a: number; c: string; }; }; }
1534+
>o : number
1535+
>2 : 2
1536+
>c : { 0: { a: number; c: string; }; }
1537+
>{0: {a: 2, c: '213123'}} : { 0: { a: number; c: string; }; }
1538+
>0 : { a: number; c: string; }
1539+
>{a: 2, c: '213123'} : { a: number; c: string; }
1540+
>a : number
1541+
>2 : 2
1542+
>c : string
1543+
>'213123' : "213123"
1544+

tests/cases/conformance/types/conditional/conditionalTypes1.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,15 @@ declare interface ExtractFooBar<FB extends FooBar> { }
341341
type Extracted<Struct> = {
342342
[K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
343343
}
344+
345+
// Repro from #22985
346+
347+
type RecursivePartial<T> = {
348+
[P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
349+
T[P] extends object ? RecursivePartial<T[P]> : T[P];
350+
};
351+
352+
declare function assign<T>(o: T, a: RecursivePartial<T>): void;
353+
354+
var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
355+
assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})

0 commit comments

Comments
 (0)