Skip to content

Commit 4e85864

Browse files
committed
Merge pull request microsoft#3823 from Microsoft/strictObjectLiterals
Strict object literal assignment checking
2 parents d057f56 + 5f7bc51 commit 4e85864

File tree

217 files changed

+3372
-5955
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

217 files changed

+3372
-5955
lines changed

src/compiler/checker.ts

+194-86
Large diffs are not rendered by default.

src/compiler/diagnosticInformationMap.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ namespace ts {
254254
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." },
255255
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." },
256256
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." },
257+
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}'." },
257258
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
258259
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." },
259260
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." },

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,10 @@
10051005
"category": "Error",
10061006
"code": 2352
10071007
},
1008+
"Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": {
1009+
"category": "Error",
1010+
"code": 2353
1011+
},
10081012
"No best common type exists among return expressions.": {
10091013
"category": "Error",
10101014
"code": 2354

src/compiler/types.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -1762,10 +1762,12 @@ namespace ts {
17621762
FromSignature = 0x00040000, // Created for signature assignment check
17631763
ObjectLiteral = 0x00080000, // Originates in an object literal
17641764
/* @internal */
1765-
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
1765+
FreshObjectLiteral = 0x00100000, // Fresh object literal type
17661766
/* @internal */
1767-
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
1768-
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
1767+
ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type
1768+
/* @internal */
1769+
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
1770+
ESSymbol = 0x00800000, // Type of symbol primitive introduced in ES6
17691771

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

1863+
/* @internal */
1864+
// Object literals are initially marked fresh. Freshness disappears following an assignment,
1865+
// before a type assertion, or when when an object literal's type is widened. The regular
1866+
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
1867+
export interface FreshObjectLiteralType extends ResolvedType {
1868+
regularType: ResolvedType; // Regular version of fresh type
1869+
}
1870+
18611871
// Just a place to cache element types of iterables and iterators
18621872
/* @internal */
18631873
export interface IterableOrIteratorType extends ObjectType, UnionType {
@@ -2211,6 +2221,7 @@ namespace ts {
22112221

22122222
export interface CompilerHost {
22132223
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
2224+
getCancellationToken?(): CancellationToken;
22142225
getDefaultLibFileName(options: CompilerOptions): string;
22152226
writeFile: WriteFileCallback;
22162227
getCurrentDirectory(): string;

src/harness/fourslash.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ module FourSlash {
2626
export interface FourSlashFile {
2727
// The contents of the file (with markers, etc stripped out)
2828
content: string;
29-
3029
fileName: string;
31-
30+
version: number;
3231
// File-specific options (name/value pairs)
3332
fileOptions: { [index: string]: string; };
3433
}

src/harness/loggedIO.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface FindFileResult {
1212
}
1313

1414
interface IOLog {
15+
timestamp: string;
1516
arguments: string[];
1617
executingPath: string;
1718
currentDirectory: string;

src/server/client.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ namespace ts.server {
202202
return {
203203
isMemberCompletion: false,
204204
isNewIdentifierLocation: false,
205-
entries: response.body,
206-
fileName: fileName,
207-
position: position
205+
entries: response.body
208206
};
209207
}
210208

src/services/services.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,7 @@ namespace ts {
11051105
}
11061106

11071107
export interface HighlightSpan {
1108+
fileName?: string;
11081109
textSpan: TextSpan;
11091110
kind: string;
11101111
}
@@ -1411,7 +1412,9 @@ namespace ts {
14111412
* @param fileName The name of the file to be released
14121413
* @param compilationSettings The compilation settings used to acquire the file
14131414
*/
1414-
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void
1415+
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
1416+
1417+
reportStats(): string;
14151418
}
14161419

14171420
// TODO: move these to enums

src/services/shims.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,11 @@ namespace ts {
454454
}
455455
}
456456

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

461-
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
461+
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; code: number; } {
462462
return {
463463
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
464464
start: diagnostic.start,

tests/baselines/reference/ES5For-of30.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'string | number' is not an array type.
1+
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,6): error TS2461: Type 'number | string' is not an array type.
22
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'.
33
tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,14): error TS2322: Type 'string' is not assignable to type 'number'.
44

@@ -8,7 +8,7 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-of30.ts(3,14): error
88
var tuple: [number, string] = [2, "3"];
99
for ([a = 1, b = ""] of tuple) {
1010
~~~~~~~~~~~~~~~
11-
!!! error TS2461: Type 'string | number' is not an array type.
11+
!!! error TS2461: Type 'number | string' is not an array type.
1212
~
1313
!!! error TS2322: Type 'number' is not assignable to type 'string'.
1414
~
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6): error TS2322: Type 'string | number' is not assignable to type 'string'.
1+
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6): error TS2322: Type 'number | string' is not assignable to type 'string'.
22
Type 'number' is not assignable to type 'string'.
33

44

@@ -7,5 +7,5 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck11.ts(3,6)
77
var v: string;
88
for (v of union) { }
99
~
10-
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
10+
!!! error TS2322: Type 'number | string' is not assignable to type 'string'.
1111
!!! error TS2322: Type 'number' is not assignable to type 'string'.

tests/baselines/reference/ES5For-ofTypeCheck5.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ var union: string | number[];
33
>union : string | number[]
44

55
for (var v of union) { }
6-
>v : string | number
6+
>v : number | string
77
>union : string | number[]
88

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts(2,15): error TS2461: Type 'number | symbol | string[]' is not an array type.
1+
tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts(2,15): error TS2461: Type 'string[] | number | symbol' is not an array type.
22

33

44
==== tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck9.ts (1 errors) ====
55
var union: string | string[] | number | symbol;
66
for (let v of union) { }
77
~~~~~
8-
!!! error TS2461: Type 'number | symbol | string[]' is not an array type.
8+
!!! error TS2461: Type 'string[] | number | symbol' is not an array type.

tests/baselines/reference/TypeGuardWithEnumUnion.types

+8-8
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ enum Color { R, G, B }
66
>B : Color
77

88
function f1(x: Color | string) {
9-
>f1 : (x: string | Color) => void
10-
>x : string | Color
9+
>f1 : (x: Color | string) => void
10+
>x : Color | string
1111
>Color : Color
1212

1313
if (typeof x === "number") {
1414
>typeof x === "number" : boolean
1515
>typeof x : string
16-
>x : string | Color
16+
>x : Color | string
1717
>"number" : string
1818

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

3737
function f2(x: Color | string | string[]) {
38-
>f2 : (x: string | Color | string[]) => void
39-
>x : string | Color | string[]
38+
>f2 : (x: Color | string | string[]) => void
39+
>x : Color | string | string[]
4040
>Color : Color
4141

4242
if (typeof x === "object") {
4343
>typeof x === "object" : boolean
4444
>typeof x : string
45-
>x : string | Color | string[]
45+
>x : Color | string | string[]
4646
>"object" : string
4747

4848
var y = x;
@@ -55,7 +55,7 @@ function f2(x: Color | string | string[]) {
5555
if (typeof x === "number") {
5656
>typeof x === "number" : boolean
5757
>typeof x : string
58-
>x : string | Color | string[]
58+
>x : Color | string | string[]
5959
>"number" : string
6060

6161
var z = x;
@@ -77,7 +77,7 @@ function f2(x: Color | string | string[]) {
7777
if (typeof x === "string") {
7878
>typeof x === "string" : boolean
7979
>typeof x : string
80-
>x : string | Color | string[]
80+
>x : Color | string | string[]
8181
>"string" : string
8282

8383
var a = x;

tests/baselines/reference/aliasUsageInOrExpression.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var d2: IHasVisualizationModel = i || moduleA;
3434
var d2: IHasVisualizationModel = moduleA || i;
3535
>d2 : IHasVisualizationModel
3636
>IHasVisualizationModel : IHasVisualizationModel
37-
>moduleA || i : IHasVisualizationModel
37+
>moduleA || i : typeof moduleA
3838
>moduleA : typeof moduleA
3939
>i : IHasVisualizationModel
4040

tests/baselines/reference/arrayBestCommonTypes.types

+28-28
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ module EmptyTypes {
294294

295295
// Order matters here so test all the variants
296296
var a1 = [{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }];
297-
>a1 : { x: any; y: string; }[]
298-
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : { x: any; y: string; }[]
297+
>a1 : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
298+
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
299299
>{ x: 0, y: 'a' } : { x: number; y: string; }
300300
>x : number
301301
>0 : number
@@ -313,8 +313,8 @@ module EmptyTypes {
313313
>'a' : string
314314

315315
var a2 = [{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }];
316-
>a2 : { x: any; y: string; }[]
317-
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
316+
>a2 : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
317+
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
318318
>{ x: anyObj, y: 'a' } : { x: any; y: string; }
319319
>x : any
320320
>anyObj : any
@@ -332,8 +332,8 @@ module EmptyTypes {
332332
>'a' : string
333333

334334
var a3 = [{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }];
335-
>a3 : { x: any; y: string; }[]
336-
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
335+
>a3 : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
336+
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
337337
>{ x: 0, y: 'a' } : { x: number; y: string; }
338338
>x : number
339339
>0 : number
@@ -366,22 +366,22 @@ module EmptyTypes {
366366
>base2 : typeof base2
367367

368368
var b1 = [baseObj, base2Obj, ifaceObj];
369-
>b1 : iface[]
370-
>[baseObj, base2Obj, ifaceObj] : iface[]
369+
>b1 : base[]
370+
>[baseObj, base2Obj, ifaceObj] : base[]
371371
>baseObj : base
372372
>base2Obj : base2
373373
>ifaceObj : iface
374374

375375
var b2 = [base2Obj, baseObj, ifaceObj];
376-
>b2 : iface[]
377-
>[base2Obj, baseObj, ifaceObj] : iface[]
376+
>b2 : base2[]
377+
>[base2Obj, baseObj, ifaceObj] : base2[]
378378
>base2Obj : base2
379379
>baseObj : base
380380
>ifaceObj : iface
381381

382382
var b3 = [baseObj, ifaceObj, base2Obj];
383-
>b3 : iface[]
384-
>[baseObj, ifaceObj, base2Obj] : iface[]
383+
>b3 : base[]
384+
>[baseObj, ifaceObj, base2Obj] : base[]
385385
>baseObj : base
386386
>ifaceObj : iface
387387
>base2Obj : base2
@@ -639,7 +639,7 @@ module NonEmptyTypes {
639639
>x : number
640640
>y : base
641641
>base : base
642-
>[{ x: 7, y: new derived() }, { x: 5, y: new base() }] : { x: number; y: base; }[]
642+
>[{ x: 7, y: new derived() }, { x: 5, y: new base() }] : ({ x: number; y: derived; } | { x: number; y: base; })[]
643643
>{ x: 7, y: new derived() } : { x: number; y: derived; }
644644
>x : number
645645
>7 : number
@@ -658,7 +658,7 @@ module NonEmptyTypes {
658658
>x : boolean
659659
>y : base
660660
>base : base
661-
>[{ x: true, y: new derived() }, { x: false, y: new base() }] : { x: boolean; y: base; }[]
661+
>[{ x: true, y: new derived() }, { x: false, y: new base() }] : ({ x: boolean; y: derived; } | { x: boolean; y: base; })[]
662662
>{ x: true, y: new derived() } : { x: boolean; y: derived; }
663663
>x : boolean
664664
>true : boolean
@@ -697,8 +697,8 @@ module NonEmptyTypes {
697697

698698
// Order matters here so test all the variants
699699
var a1 = [{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }];
700-
>a1 : { x: any; y: string; }[]
701-
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : { x: any; y: string; }[]
700+
>a1 : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
701+
>[{ x: 0, y: 'a' }, { x: 'a', y: 'a' }, { x: anyObj, y: 'a' }] : ({ x: number; y: string; } | { x: string; y: string; } | { x: any; y: string; })[]
702702
>{ x: 0, y: 'a' } : { x: number; y: string; }
703703
>x : number
704704
>0 : number
@@ -716,8 +716,8 @@ module NonEmptyTypes {
716716
>'a' : string
717717

718718
var a2 = [{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }];
719-
>a2 : { x: any; y: string; }[]
720-
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
719+
>a2 : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
720+
>[{ x: anyObj, y: 'a' }, { x: 0, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: any; y: string; } | { x: number; y: string; } | { x: string; y: string; })[]
721721
>{ x: anyObj, y: 'a' } : { x: any; y: string; }
722722
>x : any
723723
>anyObj : any
@@ -735,8 +735,8 @@ module NonEmptyTypes {
735735
>'a' : string
736736

737737
var a3 = [{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }];
738-
>a3 : { x: any; y: string; }[]
739-
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : { x: any; y: string; }[]
738+
>a3 : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
739+
>[{ x: 0, y: 'a' }, { x: anyObj, y: 'a' }, { x: 'a', y: 'a' }] : ({ x: number; y: string; } | { x: any; y: string; } | { x: string; y: string; })[]
740740
>{ x: 0, y: 'a' } : { x: number; y: string; }
741741
>x : number
742742
>0 : number
@@ -769,29 +769,29 @@ module NonEmptyTypes {
769769
>base2 : typeof base2
770770

771771
var b1 = [baseObj, base2Obj, ifaceObj];
772-
>b1 : iface[]
773-
>[baseObj, base2Obj, ifaceObj] : iface[]
772+
>b1 : (base | base2 | iface)[]
773+
>[baseObj, base2Obj, ifaceObj] : (base | base2 | iface)[]
774774
>baseObj : base
775775
>base2Obj : base2
776776
>ifaceObj : iface
777777

778778
var b2 = [base2Obj, baseObj, ifaceObj];
779-
>b2 : iface[]
780-
>[base2Obj, baseObj, ifaceObj] : iface[]
779+
>b2 : (base2 | base | iface)[]
780+
>[base2Obj, baseObj, ifaceObj] : (base2 | base | iface)[]
781781
>base2Obj : base2
782782
>baseObj : base
783783
>ifaceObj : iface
784784

785785
var b3 = [baseObj, ifaceObj, base2Obj];
786-
>b3 : iface[]
787-
>[baseObj, ifaceObj, base2Obj] : iface[]
786+
>b3 : (base | iface | base2)[]
787+
>[baseObj, ifaceObj, base2Obj] : (base | iface | base2)[]
788788
>baseObj : base
789789
>ifaceObj : iface
790790
>base2Obj : base2
791791

792792
var b4 = [ifaceObj, baseObj, base2Obj];
793-
>b4 : iface[]
794-
>[ifaceObj, baseObj, base2Obj] : iface[]
793+
>b4 : (iface | base | base2)[]
794+
>[ifaceObj, baseObj, base2Obj] : (iface | base | base2)[]
795795
>ifaceObj : iface
796796
>baseObj : base
797797
>base2Obj : base2

0 commit comments

Comments
 (0)