Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
340 changes: 167 additions & 173 deletions tsc/internal/checker/checker.go

Large diffs are not rendered by default.

8 changes: 2 additions & 6 deletions tsc/internal/checker/inference.go
Original file line number Diff line number Diff line change
Expand Up @@ -1154,12 +1154,8 @@ func (c *Checker) resolveReverseMappedTypeMembers(t *Type) {
}

func (c *Checker) getTypeOfReverseMappedSymbol(symbol *ast.Symbol) *Type {
links := c.valueSymbolLinks.Get(symbol)
if links.resolvedType == nil {
reverseLinks := c.ReverseMappedSymbolLinks.Get(symbol)
links.resolvedType = core.OrElse(c.inferReverseMappedType(reverseLinks.propertyType, reverseLinks.mappedType, reverseLinks.constraintType), c.unknownType)
}
return links.resolvedType
reverseLinks := c.ReverseMappedSymbolLinks.Get(symbol)
return core.OrElse(c.inferReverseMappedType(reverseLinks.propertyType, reverseLinks.mappedType, reverseLinks.constraintType), c.unknownType)
}

// If the original mapped type had an intersection constraint we extract its components,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
circularIndexedPropertyInstantiation.ts(3,35): error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
circularIndexedPropertyInstantiation.ts(5,13): error TS2344: Type '"false"' does not satisfy the constraint '"true"'.


==== circularIndexedPropertyInstantiation.ts (2 errors) ====
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
~~~~~~
!!! error TS2502: '"true"' is referenced directly or indirectly in its own type annotation.
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;
~~~~~~~
!!! error TS2344: Type '"false"' does not satisfy the constraint '"true"'.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [tests/cases/compiler/circularIndexedPropertyInstantiation.ts] ////

//// [circularIndexedPropertyInstantiation.ts]
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
let f1: Foo<"true", {}>;
let f2: Foo<"false", {}>;

//// [circularIndexedPropertyInstantiation.js]
"use strict";
// Repro from #14837
let f1;
let f2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//// [tests/cases/compiler/circularIndexedPropertyInstantiation.ts] ////

=== circularIndexedPropertyInstantiation.ts ===
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
>Foo : Symbol(Foo, Decl(circularIndexedPropertyInstantiation.ts, 0, 0))
>T : Symbol(T, Decl(circularIndexedPropertyInstantiation.ts, 2, 9))
>B : Symbol(B, Decl(circularIndexedPropertyInstantiation.ts, 2, 26))
>"true" : Symbol("true", Decl(circularIndexedPropertyInstantiation.ts, 2, 33))
>Foo : Symbol(Foo, Decl(circularIndexedPropertyInstantiation.ts, 0, 0))
>T : Symbol(T, Decl(circularIndexedPropertyInstantiation.ts, 2, 9))
>Foo : Symbol(Foo, Decl(circularIndexedPropertyInstantiation.ts, 0, 0))
>T : Symbol(T, Decl(circularIndexedPropertyInstantiation.ts, 2, 9))
>B : Symbol(B, Decl(circularIndexedPropertyInstantiation.ts, 2, 26))
>T : Symbol(T, Decl(circularIndexedPropertyInstantiation.ts, 2, 9))

let f1: Foo<"true", {}>;
>f1 : Symbol(f1, Decl(circularIndexedPropertyInstantiation.ts, 3, 3))
>Foo : Symbol(Foo, Decl(circularIndexedPropertyInstantiation.ts, 0, 0))

let f2: Foo<"false", {}>;
>f2 : Symbol(f2, Decl(circularIndexedPropertyInstantiation.ts, 4, 3))
>Foo : Symbol(Foo, Decl(circularIndexedPropertyInstantiation.ts, 0, 0))

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//// [tests/cases/compiler/circularIndexedPropertyInstantiation.ts] ////

=== circularIndexedPropertyInstantiation.ts ===
// Repro from #14837

type Foo<T extends "true", B> = { "true": Foo<T, Foo<T, B>> }[T];
>Foo : Foo<T, B>
>"true" : Foo<T, Foo<T, B>>

let f1: Foo<"true", {}>;
>f1 : any

let f2: Foo<"false", {}>;
>f2 : unknown

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
circularInitializerInference.ts(6,14): error TS2695: Left side of comma operator is unused and has no side effects.
circularInitializerInference.ts(9,20): error TS2695: Left side of comma operator is unused and has no side effects.
circularInitializerInference.ts(9,20): error TS2695: Left side of comma operator is unused and has no side effects.


==== circularInitializerInference.ts (3 errors) ====
export {};

type IsAny<Type> = 0 extends (1 & Type) ? true : false;
type Assert<Condition extends true> = Condition;

var comma = (comma, 3);
~~~~~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
type CommaInference = Assert<IsAny<typeof comma>>;

var nestedComma = (comma, nestedComma, comma);
~~~~~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
~~~~~~~~~~~~~~~~~~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
type NestedCommaInference = Assert<IsAny<typeof nestedComma>>;

var assignment = (assignment = 2);
type AssignmentInference = Assert<IsAny<typeof assignment>>;

var nestedAssignment = (nestedAssignment = nestedAssignment = 2);
type NestedAssignmentInference = Assert<IsAny<typeof nestedAssignment>>;

var conditional = conditional ? 0 : 1;
type ConditionalInference = Assert<IsAny<typeof conditional>>;

var logicalAnd = logicalAnd && "";
type LogicalAndInference = Assert<IsAny<typeof logicalAnd>>;

var propertyAccess = { member: propertyAccess.member };
type PropertyAccessInference = Assert<IsAny<typeof propertyAccess>>;

const nonCircular: number = 3;
type NonCircularInference = Assert<IsAny<typeof nonCircular> extends false ? true : false>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// [tests/cases/compiler/circularInitializerInference.ts] ////

//// [circularInitializerInference.ts]
export {};

type IsAny<Type> = 0 extends (1 & Type) ? true : false;
type Assert<Condition extends true> = Condition;

var comma = (comma, 3);
type CommaInference = Assert<IsAny<typeof comma>>;

var nestedComma = (comma, nestedComma, comma);
type NestedCommaInference = Assert<IsAny<typeof nestedComma>>;

var assignment = (assignment = 2);
type AssignmentInference = Assert<IsAny<typeof assignment>>;

var nestedAssignment = (nestedAssignment = nestedAssignment = 2);
type NestedAssignmentInference = Assert<IsAny<typeof nestedAssignment>>;

var conditional = conditional ? 0 : 1;
type ConditionalInference = Assert<IsAny<typeof conditional>>;

var logicalAnd = logicalAnd && "";
type LogicalAndInference = Assert<IsAny<typeof logicalAnd>>;

var propertyAccess = { member: propertyAccess.member };
type PropertyAccessInference = Assert<IsAny<typeof propertyAccess>>;

const nonCircular: number = 3;
type NonCircularInference = Assert<IsAny<typeof nonCircular> extends false ? true : false>;

//// [circularInitializerInference.js]
var comma = (comma, 3);
var nestedComma = (comma, nestedComma, comma);
var assignment = (assignment = 2);
var nestedAssignment = (nestedAssignment = nestedAssignment = 2);
var conditional = conditional ? 0 : 1;
var logicalAnd = logicalAnd && "";
var propertyAccess = { member: propertyAccess.member };
const nonCircular = 3;
export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//// [tests/cases/compiler/circularInitializerInference.ts] ////

=== circularInitializerInference.ts ===
export {};

type IsAny<Type> = 0 extends (1 & Type) ? true : false;
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>Type : Symbol(Type, Decl(circularInitializerInference.ts, 2, 11))
>Type : Symbol(Type, Decl(circularInitializerInference.ts, 2, 11))

type Assert<Condition extends true> = Condition;
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>Condition : Symbol(Condition, Decl(circularInitializerInference.ts, 3, 12))
>Condition : Symbol(Condition, Decl(circularInitializerInference.ts, 3, 12))

var comma = (comma, 3);
>comma : Symbol(comma, Decl(circularInitializerInference.ts, 5, 3))
>comma : Symbol(comma, Decl(circularInitializerInference.ts, 5, 3))

type CommaInference = Assert<IsAny<typeof comma>>;
>CommaInference : Symbol(CommaInference, Decl(circularInitializerInference.ts, 5, 23))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>comma : Symbol(comma, Decl(circularInitializerInference.ts, 5, 3))

var nestedComma = (comma, nestedComma, comma);
>nestedComma : Symbol(nestedComma, Decl(circularInitializerInference.ts, 8, 3))
>comma : Symbol(comma, Decl(circularInitializerInference.ts, 5, 3))
>nestedComma : Symbol(nestedComma, Decl(circularInitializerInference.ts, 8, 3))
>comma : Symbol(comma, Decl(circularInitializerInference.ts, 5, 3))

type NestedCommaInference = Assert<IsAny<typeof nestedComma>>;
>NestedCommaInference : Symbol(NestedCommaInference, Decl(circularInitializerInference.ts, 8, 46))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>nestedComma : Symbol(nestedComma, Decl(circularInitializerInference.ts, 8, 3))

var assignment = (assignment = 2);
>assignment : Symbol(assignment, Decl(circularInitializerInference.ts, 11, 3))
>assignment : Symbol(assignment, Decl(circularInitializerInference.ts, 11, 3))

type AssignmentInference = Assert<IsAny<typeof assignment>>;
>AssignmentInference : Symbol(AssignmentInference, Decl(circularInitializerInference.ts, 11, 34))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>assignment : Symbol(assignment, Decl(circularInitializerInference.ts, 11, 3))

var nestedAssignment = (nestedAssignment = nestedAssignment = 2);
>nestedAssignment : Symbol(nestedAssignment, Decl(circularInitializerInference.ts, 14, 3))
>nestedAssignment : Symbol(nestedAssignment, Decl(circularInitializerInference.ts, 14, 3))
>nestedAssignment : Symbol(nestedAssignment, Decl(circularInitializerInference.ts, 14, 3))

type NestedAssignmentInference = Assert<IsAny<typeof nestedAssignment>>;
>NestedAssignmentInference : Symbol(NestedAssignmentInference, Decl(circularInitializerInference.ts, 14, 65))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>nestedAssignment : Symbol(nestedAssignment, Decl(circularInitializerInference.ts, 14, 3))

var conditional = conditional ? 0 : 1;
>conditional : Symbol(conditional, Decl(circularInitializerInference.ts, 17, 3))
>conditional : Symbol(conditional, Decl(circularInitializerInference.ts, 17, 3))

type ConditionalInference = Assert<IsAny<typeof conditional>>;
>ConditionalInference : Symbol(ConditionalInference, Decl(circularInitializerInference.ts, 17, 38))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>conditional : Symbol(conditional, Decl(circularInitializerInference.ts, 17, 3))

var logicalAnd = logicalAnd && "";
>logicalAnd : Symbol(logicalAnd, Decl(circularInitializerInference.ts, 20, 3))
>logicalAnd : Symbol(logicalAnd, Decl(circularInitializerInference.ts, 20, 3))

type LogicalAndInference = Assert<IsAny<typeof logicalAnd>>;
>LogicalAndInference : Symbol(LogicalAndInference, Decl(circularInitializerInference.ts, 20, 34))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>logicalAnd : Symbol(logicalAnd, Decl(circularInitializerInference.ts, 20, 3))

var propertyAccess = { member: propertyAccess.member };
>propertyAccess : Symbol(propertyAccess, Decl(circularInitializerInference.ts, 23, 3))
>member : Symbol(member, Decl(circularInitializerInference.ts, 23, 22))
>propertyAccess : Symbol(propertyAccess, Decl(circularInitializerInference.ts, 23, 3))

type PropertyAccessInference = Assert<IsAny<typeof propertyAccess>>;
>PropertyAccessInference : Symbol(PropertyAccessInference, Decl(circularInitializerInference.ts, 23, 55))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>propertyAccess : Symbol(propertyAccess, Decl(circularInitializerInference.ts, 23, 3))

const nonCircular: number = 3;
>nonCircular : Symbol(nonCircular, Decl(circularInitializerInference.ts, 26, 5))

type NonCircularInference = Assert<IsAny<typeof nonCircular> extends false ? true : false>;
>NonCircularInference : Symbol(NonCircularInference, Decl(circularInitializerInference.ts, 26, 30))
>Assert : Symbol(Assert, Decl(circularInitializerInference.ts, 2, 55))
>IsAny : Symbol(IsAny, Decl(circularInitializerInference.ts, 0, 10))
>nonCircular : Symbol(nonCircular, Decl(circularInitializerInference.ts, 26, 5))

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//// [tests/cases/compiler/circularInitializerInference.ts] ////

=== circularInitializerInference.ts ===
export {};

type IsAny<Type> = 0 extends (1 & Type) ? true : false;
>IsAny : IsAny<Type>
>true : true
>false : false

type Assert<Condition extends true> = Condition;
>Assert : Condition
>true : true

var comma = (comma, 3);
>comma : any
>(comma, 3) : 3
>comma, 3 : 3
>comma : any
>3 : 3

type CommaInference = Assert<IsAny<typeof comma>>;
>CommaInference : any
>comma : any

var nestedComma = (comma, nestedComma, comma);
>nestedComma : any
>(comma, nestedComma, comma) : any
>comma, nestedComma, comma : any
>comma, nestedComma : any
>comma : any
>nestedComma : any
>comma : any

type NestedCommaInference = Assert<IsAny<typeof nestedComma>>;
>NestedCommaInference : any
>nestedComma : any

var assignment = (assignment = 2);
>assignment : any
>(assignment = 2) : 2
>assignment = 2 : 2
>assignment : any
>2 : 2

type AssignmentInference = Assert<IsAny<typeof assignment>>;
>AssignmentInference : any
>assignment : any

var nestedAssignment = (nestedAssignment = nestedAssignment = 2);
>nestedAssignment : any
>(nestedAssignment = nestedAssignment = 2) : 2
>nestedAssignment = nestedAssignment = 2 : 2
>nestedAssignment : any
>nestedAssignment = 2 : 2
>nestedAssignment : any
>2 : 2

type NestedAssignmentInference = Assert<IsAny<typeof nestedAssignment>>;
>NestedAssignmentInference : any
>nestedAssignment : any

var conditional = conditional ? 0 : 1;
>conditional : any
>conditional ? 0 : 1 : 0 | 1
>conditional : any
>0 : 0
>1 : 1

type ConditionalInference = Assert<IsAny<typeof conditional>>;
>ConditionalInference : any
>conditional : any

var logicalAnd = logicalAnd && "";
>logicalAnd : any
>logicalAnd && "" : ""
>logicalAnd : any
>"" : ""

type LogicalAndInference = Assert<IsAny<typeof logicalAnd>>;
>LogicalAndInference : any
>logicalAnd : any

var propertyAccess = { member: propertyAccess.member };
>propertyAccess : any
>{ member: propertyAccess.member } : { member: any; }
>member : any
>propertyAccess.member : any
>propertyAccess : any
>member : any

type PropertyAccessInference = Assert<IsAny<typeof propertyAccess>>;
>PropertyAccessInference : any
>propertyAccess : any

const nonCircular: number = 3;
>nonCircular : number
>3 : 3

type NonCircularInference = Assert<IsAny<typeof nonCircular> extends false ? true : false>;
>NonCircularInference : true
>nonCircular : number
>false : false
>true : true
>false : false

Loading
Loading