Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict object literal assignment checking #3823

Merged
merged 23 commits into from
Jul 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cd0d3ba
Object literals can only have properties that exist in contextual type
ahejlsberg Jul 9, 2015
11aecee
Switch to assignability check and fix compiler bugs found by check
ahejlsberg Jul 11, 2015
3fe7591
Accepting new baselines
ahejlsberg Jul 11, 2015
f57991e
Support union and intersection types in checks
ahejlsberg Jul 11, 2015
aa26980
Addressing CR feedback
ahejlsberg Jul 13, 2015
d78fa18
Ignore freshness in subtype reduction / Treat Object as {}
ahejlsberg Jul 13, 2015
2eca3d5
Fixing bug in test
ahejlsberg Jul 13, 2015
c7b0732
Accepting new baselines
ahejlsberg Jul 13, 2015
c42b8f7
New deduplication algorithm for union types
ahejlsberg Jul 15, 2015
d34557a
Deduplication of tuple types in unions
ahejlsberg Jul 16, 2015
1a4252d
Updating fourslash tests
ahejlsberg Jul 16, 2015
7dbb69a
Accepting new baselines
ahejlsberg Jul 16, 2015
c8423d3
Getting rid of subtype reduction for union types
ahejlsberg Jul 16, 2015
eeeb05b
Fixing fourslash tests
ahejlsberg Jul 16, 2015
acd8c77
Accepting new baselines
ahejlsberg Jul 16, 2015
a05ebc4
Preserve order in union types
ahejlsberg Jul 19, 2015
3cbc3db
Fixing fourslash tests
ahejlsberg Jul 19, 2015
592319d
Accepting new baselines
ahejlsberg Jul 19, 2015
2913cb0
Merge branch 'master' into strictObjectLiterals
ahejlsberg Jul 19, 2015
155ee4b
Better error message
ahejlsberg Jul 20, 2015
967df39
Accepting new baselines
ahejlsberg Jul 20, 2015
57f1a99
Adding comma in error message
ahejlsberg Jul 21, 2015
5f7bc51
Accepting new baselines
ahejlsberg Jul 21, 2015
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
280 changes: 194 additions & 86 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ namespace ts {
Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: DiagnosticCategory.Error, key: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." },
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,10 @@
"category": "Error",
"code": 2352
},
"Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": {
"category": "Error",
"code": 2353
},
"No best common type exists among return expressions.": {
"category": "Error",
"code": 2354
Expand Down
17 changes: 14 additions & 3 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1762,10 +1762,12 @@ namespace ts {
FromSignature = 0x00040000, // Created for signature assignment check
ObjectLiteral = 0x00080000, // Originates in an object literal
/* @internal */
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
FreshObjectLiteral = 0x00100000, // Fresh object literal type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define fresh object literal in the comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a new flag here? This is set in the same place as ObjectLiteral. And when you get the regular type, you turn off FreshObjectLiteral, but not ObjectLiteral, and I don't really understand why. So a regular type is allowed to have excess properties, but it still does not need to have all the optional properties of the target in a subtype check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's related to the issue of removing freshness after the first assignment, but still remembering that the source was an object literal. It may be that we can combine the two if we give up on the first assignment bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I think we should give up the first assignment bit. I think it is a strange rule.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I don't think we can get rid of the new flag. We use TypeFlag.ObjectLiteral to indicate that a type originated in an object literal and may contain null or undefined types. We can't turn off that flag unless we also widen the type. Yet, in type assertions and during subtype reduction we want to turn off freshness but not widen.

That said, we could still drop the assignment rule. They're really orthogonal issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's drop the assignment rule.

I understand what you mean about TypeFlags.ObjectLiteral, but I still think we can use it. We actually use ContainsUndefinedOrNull and ContainsObjectLiteral for what you are talking about, not ObjectLiteral directly. For type assertions, I think it's fine to widen, we already do in the downcast direction, and I think it's fine to do it for the upcast (it uses assignability so we should be fine). For creation of a union type, we already give it TypeFlags.Union plus all the widening flags (which do not include ObjectLiteral anyway). So all the flags that getWidenedType checks for would still be there.

So I think it is safe to remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To elaborate about the type assertion case, widening would essentially do two things:

  1. null and undefined become any. They are bottom types anyway, so changing them to any should have no effect.
  2. The object literal is changed with respect to the optional-properties-being-required rule. This rule only applies to subtype, and type assertions use assignability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I admit it's still possible that I missed something, but if I did, I'd like to understand it before allowing us to have two flags that sound really similar and are easy to confuse.

/* @internal */
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type
/* @internal */
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
ESSymbol = 0x00800000, // Type of symbol primitive introduced in ES6

/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
Expand Down Expand Up @@ -1858,6 +1860,14 @@ namespace ts {
numberIndexType?: Type; // Numeric index type
}

/* @internal */
// Object literals are initially marked fresh. Freshness disappears following an assignment,
// before a type assertion, or when when an object literal's type is widened. The regular
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
export interface FreshObjectLiteralType extends ResolvedType {
regularType: ResolvedType; // Regular version of fresh type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does regular mean not fresh? Are they opposites?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are exactly the same, except the TypeFlags.FreshObjectLiteral flag is set in the fresh version.

}

// Just a place to cache element types of iterables and iterators
/* @internal */
export interface IterableOrIteratorType extends ObjectType, UnionType {
Expand Down Expand Up @@ -2211,6 +2221,7 @@ namespace ts {

export interface CompilerHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
writeFile: WriteFileCallback;
getCurrentDirectory(): string;
Expand Down
3 changes: 1 addition & 2 deletions src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ module FourSlash {
export interface FourSlashFile {
// The contents of the file (with markers, etc stripped out)
content: string;

fileName: string;

version: number;
// File-specific options (name/value pairs)
fileOptions: { [index: string]: string; };
}
Expand Down
1 change: 1 addition & 0 deletions src/harness/loggedIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface FindFileResult {
}

interface IOLog {
timestamp: string;
arguments: string[];
executingPath: string;
currentDirectory: string;
Expand Down
4 changes: 1 addition & 3 deletions src/server/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,7 @@ namespace ts.server {
return {
isMemberCompletion: false,
isNewIdentifierLocation: false,
entries: response.body,
fileName: fileName,
position: position
entries: response.body
};
}

Expand Down
5 changes: 4 additions & 1 deletion src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,7 @@ namespace ts {
}

export interface HighlightSpan {
fileName?: string;
textSpan: TextSpan;
kind: string;
}
Expand Down Expand Up @@ -1411,7 +1412,9 @@ namespace ts {
* @param fileName The name of the file to be released
* @param compilationSettings The compilation settings used to acquire the file
*/
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;

reportStats(): string;
}

// TODO: move these to enums
Expand Down
4 changes: 2 additions & 2 deletions src/services/shims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,11 @@ namespace ts {
}
}

export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; } []{
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; code: number; } []{
return diagnostics.map(d => realizeDiagnostic(d, newLine));
}

function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; code: number; } {
return {
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
start: diagnostic.start,
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/ES5For-of30.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'string | number' is not an array type.
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'number | string' is not an array type.
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,14): error TS2322: Type 'string' is not assignable to type 'number'.

Expand All @@ -8,7 +8,7 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,14): error
var tuple: [number, string] = [2, "3"];
for ([a = 1, b = ""] of tuple) {
~~~~~~~~~~~~~~~
!!! error TS2461: Type 'string | number' is not an array type.
!!! error TS2461: Type 'number | string' is not an array type.
~
!!! error TS2322: Type 'number' is not assignable to type 'string'.
~
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/ES5For-ofTypeCheck11.errors.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6): error TS2322: Type 'string | number' is not assignable to type 'string'.
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6): error TS2322: Type 'number | string' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.


Expand All @@ -7,5 +7,5 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6)
var v: string;
for (v of union) { }
~
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number | string' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
2 changes: 1 addition & 1 deletion tests/baselines/reference/ES5For-ofTypeCheck5.types
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ var union: string | number[];
>union : string | number[]

for (var v of union) { }
>v : string | number
>v : number | string
>union : string | number[]

4 changes: 2 additions & 2 deletions tests/baselines/reference/ES5For-ofTypeCheck9.errors.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts(2,15): error TS2461: Type 'number | symbol | string[]' is not an array type.
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts(2,15): error TS2461: Type 'string[] | number | symbol' is not an array type.


==== tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts (1 errors) ====
var union: string | string[] | number | symbol;
for (let v of union) { }
~~~~~
!!! error TS2461: Type 'number | symbol | string[]' is not an array type.
!!! error TS2461: Type 'string[] | number | symbol' is not an array type.
16 changes: 8 additions & 8 deletions tests/baselines/reference/TypeGuardWithEnumUnion.types
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ enum Color { R, G, B }
>B : Color

function f1(x: Color | string) {
>f1 : (x: string | Color) => void
>x : string | Color
>f1 : (x: Color | string) => void
>x : Color | string
>Color : Color

if (typeof x === "number") {
>typeof x === "number" : boolean
>typeof x : string
>x : string | Color
>x : Color | string
>"number" : string

var y = x;
Expand All @@ -35,14 +35,14 @@ function f1(x: Color | string) {
}

function f2(x: Color | string | string[]) {
>f2 : (x: string | Color | string[]) => void
>x : string | Color | string[]
>f2 : (x: Color | string | string[]) => void
>x : Color | string | string[]
>Color : Color

if (typeof x === "object") {
>typeof x === "object" : boolean
>typeof x : string
>x : string | Color | string[]
>x : Color | string | string[]
>"object" : string

var y = x;
Expand All @@ -55,7 +55,7 @@ function f2(x: Color | string | string[]) {
if (typeof x === "number") {
>typeof x === "number" : boolean
>typeof x : string
>x : string | Color | string[]
>x : Color | string | string[]
>"number" : string

var z = x;
Expand All @@ -77,7 +77,7 @@ function f2(x: Color | string | string[]) {
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | Color | string[]
>x : Color | string | string[]
>"string" : string

var a = x;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/aliasUsageInOrExpression.types
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var d2: IHasVisualizationModel = i || moduleA;
var d2: IHasVisualizationModel = moduleA || i;
>d2 : IHasVisualizationModel
>IHasVisualizationModel : IHasVisualizationModel
>moduleA || i : IHasVisualizationModel
>moduleA || i : typeof moduleA
>moduleA : typeof moduleA
>i : IHasVisualizationModel

Expand Down
56 changes: 28 additions & 28 deletions tests/baselines/reference/arrayBestCommonTypes.types
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ module EmptyTypes {

// Order matters here so test all the variants
var a1 = [{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }];
>a1 : { x: any; y: string; }[]
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : { x: any; y: string; }[]
>a1 : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
>{ x: 0, y: 'a' } : { x: number; y: string; }
>x : number
>0 : number
Expand All @@ -313,8 +313,8 @@ module EmptyTypes {
>'a' : string

var a2 = [{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }];
>a2 : { x: any; y: string; }[]
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
>a2 : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
>{ x: anyObj, y: 'a' } : { x: any; y: string; }
>x : any
>anyObj : any
Expand All @@ -332,8 +332,8 @@ module EmptyTypes {
>'a' : string

var a3 = [{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }];
>a3 : { x: any; y: string; }[]
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
>a3 : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
>{ x: 0, y: 'a' } : { x: number; y: string; }
>x : number
>0 : number
Expand Down Expand Up @@ -366,22 +366,22 @@ module EmptyTypes {
>base2 : typeof base2

var b1 = [baseObj, base2Obj, ifaceObj];
>b1 : iface[]
>[baseObj, base2Obj, ifaceObj] : iface[]
>b1 : base[]
>[baseObj, base2Obj, ifaceObj] : base[]
>baseObj : base
>base2Obj : base2
>ifaceObj : iface

var b2 = [base2Obj, baseObj, ifaceObj];
>b2 : iface[]
>[base2Obj, baseObj, ifaceObj] : iface[]
>b2 : base2[]
>[base2Obj, baseObj, ifaceObj] : base2[]
>base2Obj : base2
>baseObj : base
>ifaceObj : iface

var b3 = [baseObj, ifaceObj, base2Obj];
>b3 : iface[]
>[baseObj, ifaceObj, base2Obj] : iface[]
>b3 : base[]
>[baseObj, ifaceObj, base2Obj] : base[]
>baseObj : base
>ifaceObj : iface
>base2Obj : base2
Expand Down Expand Up @@ -639,7 +639,7 @@ module NonEmptyTypes {
>x : number
>y : base
>base : base
>[{ x: 7, y: new derived() }, { x: 5, y: new base() }] : { x: number; y: base; }[]
>[{ x: 7, y: new derived() }, { x: 5, y: new base() }] : ({ x: number; y: derived; } | { x: number; y: base; })[]
>{ x: 7, y: new derived() } : { x: number; y: derived; }
>x : number
>7 : number
Expand All @@ -658,7 +658,7 @@ module NonEmptyTypes {
>x : boolean
>y : base
>base : base
>[{ x: true, y: new derived() }, { x: false, y: new base() }] : { x: boolean; y: base; }[]
>[{ x: true, y: new derived() }, { x: false, y: new base() }] : ({ x: boolean; y: derived; } | { x: boolean; y: base; })[]
>{ x: true, y: new derived() } : { x: boolean; y: derived; }
>x : boolean
>true : boolean
Expand Down Expand Up @@ -697,8 +697,8 @@ module NonEmptyTypes {

// Order matters here so test all the variants
var a1 = [{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }];
>a1 : { x: any; y: string; }[]
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : { x: any; y: string; }[]
>a1 : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
>{ x: 0, y: 'a' } : { x: number; y: string; }
>x : number
>0 : number
Expand All @@ -716,8 +716,8 @@ module NonEmptyTypes {
>'a' : string

var a2 = [{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }];
>a2 : { x: any; y: string; }[]
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
>a2 : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
>{ x: anyObj, y: 'a' } : { x: any; y: string; }
>x : any
>anyObj : any
Expand All @@ -735,8 +735,8 @@ module NonEmptyTypes {
>'a' : string

var a3 = [{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }];
>a3 : { x: any; y: string; }[]
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
>a3 : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
>{ x: 0, y: 'a' } : { x: number; y: string; }
>x : number
>0 : number
Expand Down Expand Up @@ -769,29 +769,29 @@ module NonEmptyTypes {
>base2 : typeof base2

var b1 = [baseObj, base2Obj, ifaceObj];
>b1 : iface[]
>[baseObj, base2Obj, ifaceObj] : iface[]
>b1 : (base | base2 | iface)[]
>[baseObj, base2Obj, ifaceObj] : (base | base2 | iface)[]
>baseObj : base
>base2Obj : base2
>ifaceObj : iface

var b2 = [base2Obj, baseObj, ifaceObj];
>b2 : iface[]
>[base2Obj, baseObj, ifaceObj] : iface[]
>b2 : (base2 | base | iface)[]
>[base2Obj, baseObj, ifaceObj] : (base2 | base | iface)[]
>base2Obj : base2
>baseObj : base
>ifaceObj : iface

var b3 = [baseObj, ifaceObj, base2Obj];
>b3 : iface[]
>[baseObj, ifaceObj, base2Obj] : iface[]
>b3 : (base | iface | base2)[]
>[baseObj, ifaceObj, base2Obj] : (base | iface | base2)[]
>baseObj : base
>ifaceObj : iface
>base2Obj : base2

var b4 = [ifaceObj, baseObj, base2Obj];
>b4 : iface[]
>[ifaceObj, baseObj, base2Obj] : iface[]
>b4 : (iface | base | base2)[]
>[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[]
>ifaceObj : iface
>baseObj : base
>base2Obj : base2
Expand Down
Loading