Skip to content

Commit

Permalink
add strictTuples flag giving tuples known length
Browse files Browse the repository at this point in the history
  • Loading branch information
KiaraGrouwstra committed Aug 19, 2017
1 parent d03d107 commit 1f77317
Show file tree
Hide file tree
Showing 27 changed files with 185 additions and 69 deletions.
7 changes: 7 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace ts {
const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters;
const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System;
const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks;
const strictTuples = compilerOptions.strictTuples === undefined ? compilerOptions.strict : compilerOptions.strictTuples;
const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny;
const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis;

Expand Down Expand Up @@ -7161,6 +7162,12 @@ namespace ts {
property.type = typeParameter;
properties.push(property);
}
if (strictTuples) {
const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String);
lengthSymbol.type = getLiteralType(arity);
lengthSymbol.checkFlags = CheckFlags.Readonly;
properties.push(lengthSymbol);
}
const type = <GenericType & InterfaceTypeWithDeclaredMembers>createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference);
type.typeParameters = typeParameters;
type.outerTypeParameters = undefined;
Expand Down
7 changes: 7 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_null_checks
},
{
name: "strictTuples",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_tuple_checks
},
{
name: "noImplicitThis",
type: "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3302,6 +3302,10 @@
"category": "Message",
"code": 6185
},
"Enable strict tuple checks.": {
"category": "Message",
"code": 6187
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3622,6 +3622,7 @@ namespace ts {
sourceRoot?: string;
strict?: boolean;
strictNullChecks?: boolean; // Always combine with strict property
strictTuples?: boolean;
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
Expand Down
6 changes: 6 additions & 0 deletions src/harness/unittests/configurationExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ namespace ts {
strictNullChecks: false
}
},
"/dev/tsconfig.strictTuples.json": {
extends: "./tsconfig",
compilerOptions: {
strictTuples: false
}
},
"/dev/configs/base.json": {
compilerOptions: {
allowJs: true,
Expand Down
4 changes: 4 additions & 0 deletions src/harness/unittests/transpile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,10 @@ var x = 0;`, {
options: { compilerOptions: { strictNullChecks: true }, fileName: "input.js", reportDiagnostics: true }
});

transpilesCorrectly("Supports setting 'strictTuples'", "x;", {
options: { compilerOptions: { strictTuples: true }, fileName: "input.js", reportDiagnostics: true }
});

transpilesCorrectly("Supports setting 'stripInternal'", "x;", {
options: { compilerOptions: { stripInternal: true }, fileName: "input.js", reportDiagnostics: true }
});
Expand Down
1 change: 1 addition & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2448,6 +2448,7 @@ namespace ts.server.protocol {
sourceRoot?: string;
strict?: boolean;
strictNullChecks?: boolean;
strictTuples?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget | ts.ScriptTarget;
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/genericTypeAliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ type Strange<T> = string; // Type parameter not used
var s: Strange<number>;
s = "hello";

interface Tuple<A, B> {
interface AB<A, B> {
a: A;
b: B;
}

type Pair<T> = Tuple<T, T>;
type Pair<T> = AB<T, T>;

interface TaggedPair<T> extends Pair<T> {
tag: string;
Expand Down
32 changes: 16 additions & 16 deletions tests/baselines/reference/genericTypeAliases.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -124,29 +124,29 @@ var s: Strange<number>;
s = "hello";
>s : Symbol(s, Decl(genericTypeAliases.ts, 38, 3))

interface Tuple<A, B> {
>Tuple : Symbol(Tuple, Decl(genericTypeAliases.ts, 39, 12))
>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 16))
>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 18))
interface AB<A, B> {
>AB : Symbol(AB, Decl(genericTypeAliases.ts, 39, 12))
>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 13))
>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 15))

a: A;
>a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23))
>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 16))
>a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20))
>A : Symbol(A, Decl(genericTypeAliases.ts, 41, 13))

b: B;
>b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9))
>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 18))
>b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9))
>B : Symbol(B, Decl(genericTypeAliases.ts, 41, 15))
}

type Pair<T> = Tuple<T, T>;
type Pair<T> = AB<T, T>;
>Pair : Symbol(Pair, Decl(genericTypeAliases.ts, 44, 1))
>T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10))
>Tuple : Symbol(Tuple, Decl(genericTypeAliases.ts, 39, 12))
>AB : Symbol(AB, Decl(genericTypeAliases.ts, 39, 12))
>T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10))
>T : Symbol(T, Decl(genericTypeAliases.ts, 46, 10))

interface TaggedPair<T> extends Pair<T> {
>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 27))
>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 24))
>T : Symbol(T, Decl(genericTypeAliases.ts, 48, 21))
>Pair : Symbol(Pair, Decl(genericTypeAliases.ts, 44, 1))
>T : Symbol(T, Decl(genericTypeAliases.ts, 48, 21))
Expand All @@ -157,17 +157,17 @@ interface TaggedPair<T> extends Pair<T> {

var p: TaggedPair<number>;
>p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3))
>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 27))
>TaggedPair : Symbol(TaggedPair, Decl(genericTypeAliases.ts, 46, 24))

p.a = 1;
>p.a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23))
>p.a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20))
>p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3))
>a : Symbol(Tuple.a, Decl(genericTypeAliases.ts, 41, 23))
>a : Symbol(AB.a, Decl(genericTypeAliases.ts, 41, 20))

p.b = 2;
>p.b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9))
>p.b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9))
>p : Symbol(p, Decl(genericTypeAliases.ts, 52, 3))
>b : Symbol(Tuple.b, Decl(genericTypeAliases.ts, 42, 9))
>b : Symbol(AB.b, Decl(genericTypeAliases.ts, 42, 9))

p.tag = "test";
>p.tag : Symbol(TaggedPair.tag, Decl(genericTypeAliases.ts, 48, 41))
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/genericTypeAliases.types
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ s = "hello";
>s : string
>"hello" : "hello"

interface Tuple<A, B> {
>Tuple : Tuple<A, B>
interface AB<A, B> {
>AB : AB<A, B>
>A : A
>B : B

Expand All @@ -172,17 +172,17 @@ interface Tuple<A, B> {
>B : B
}

type Pair<T> = Tuple<T, T>;
>Pair : Tuple<T, T>
type Pair<T> = AB<T, T>;
>Pair : AB<T, T>
>T : T
>Tuple : Tuple<A, B>
>AB : AB<A, B>
>T : T
>T : T

interface TaggedPair<T> extends Pair<T> {
>TaggedPair : TaggedPair<T>
>T : T
>Pair : Tuple<T, T>
>Pair : AB<T, T>
>T : T

tag: string;
Expand Down
10 changes: 5 additions & 5 deletions tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
//// [nominalSubtypeCheckOfTypeParameter.ts]
interface Tuple<T, S> {
interface BinaryTuple<T, S> {
first: T
second: S
second: S
}

interface Sequence<T> {
hasNext(): boolean
pop(): T
zip<S>(seq: Sequence<S>): Sequence<Tuple<T, S>>
pop(): T
zip<S>(seq: Sequence<S>): Sequence<BinaryTuple<T, S>>
}

// error, despite the fact that the code explicitly says List<T> extends Sequence<T>, the current rules for infinitely expanding type references
// perform nominal subtyping checks that allow variance for type arguments, but not nominal subtyping for the generic type itself
interface List<T> extends Sequence<T> {
getLength(): number
zip<S>(seq: Sequence<S>): List<Tuple<T, S>>
zip<S>(seq: Sequence<S>): List<BinaryTuple<T, S>>
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
=== tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts ===
interface Tuple<T, S> {
>Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 16))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 18))
interface BinaryTuple<T, S> {
>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 22))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 24))

first: T
>first : Symbol(Tuple.first, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 23))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 16))
>first : Symbol(BinaryTuple.first, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 29))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 22))

second: S
>second : Symbol(Tuple.second, Decl(nominalSubtypeCheckOfTypeParameter.ts, 1, 12))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 18))
second: S
>second : Symbol(BinaryTuple.second, Decl(nominalSubtypeCheckOfTypeParameter.ts, 1, 12))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 24))
}

interface Sequence<T> {
Expand All @@ -20,20 +20,20 @@ interface Sequence<T> {
hasNext(): boolean
>hasNext : Symbol(Sequence.hasNext, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 23))

pop(): T
pop(): T
>pop : Symbol(Sequence.pop, Decl(nominalSubtypeCheckOfTypeParameter.ts, 6, 22))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 19))

zip<S>(seq: Sequence<S>): Sequence<Tuple<T, S>>
>zip : Symbol(Sequence.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 7, 14))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10))
>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 13))
zip<S>(seq: Sequence<S>): Sequence<BinaryTuple<T, S>>
>zip : Symbol(Sequence.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 7, 12))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8))
>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 11))
>Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8))
>Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1))
>Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 5, 19))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 10))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 8, 8))
}

// error, despite the fact that the code explicitly says List<T> extends Sequence<T>, the current rules for infinitely expanding type references
Expand All @@ -47,15 +47,15 @@ interface List<T> extends Sequence<T> {
getLength(): number
>getLength : Symbol(List.getLength, Decl(nominalSubtypeCheckOfTypeParameter.ts, 13, 39))

zip<S>(seq: Sequence<S>): List<Tuple<T, S>>
zip<S>(seq: Sequence<S>): List<BinaryTuple<T, S>>
>zip : Symbol(List.zip, Decl(nominalSubtypeCheckOfTypeParameter.ts, 14, 23))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10))
>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 13))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8))
>seq : Symbol(seq, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 11))
>Sequence : Symbol(Sequence, Decl(nominalSubtypeCheckOfTypeParameter.ts, 3, 1))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8))
>List : Symbol(List, Decl(nominalSubtypeCheckOfTypeParameter.ts, 9, 1))
>Tuple : Symbol(Tuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>BinaryTuple : Symbol(BinaryTuple, Decl(nominalSubtypeCheckOfTypeParameter.ts, 0, 0))
>T : Symbol(T, Decl(nominalSubtypeCheckOfTypeParameter.ts, 13, 15))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 10))
>S : Symbol(S, Decl(nominalSubtypeCheckOfTypeParameter.ts, 15, 8))
}

20 changes: 10 additions & 10 deletions tests/baselines/reference/nominalSubtypeCheckOfTypeParameter.types
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
=== tests/cases/conformance/types/typeRelationships/recursiveTypes/nominalSubtypeCheckOfTypeParameter.ts ===
interface Tuple<T, S> {
>Tuple : Tuple<T, S>
interface BinaryTuple<T, S> {
>BinaryTuple : BinaryTuple<T, S>
>T : T
>S : S

first: T
>first : T
>T : T

second: S
second: S
>second : S
>S : S
}
Expand All @@ -20,18 +20,18 @@ interface Sequence<T> {
hasNext(): boolean
>hasNext : () => boolean

pop(): T
pop(): T
>pop : () => T
>T : T

zip<S>(seq: Sequence<S>): Sequence<Tuple<T, S>>
>zip : <S>(seq: Sequence<S>) => Sequence<Tuple<T, S>>
zip<S>(seq: Sequence<S>): Sequence<BinaryTuple<T, S>>
>zip : <S>(seq: Sequence<S>) => Sequence<BinaryTuple<T, S>>
>S : S
>seq : Sequence<S>
>Sequence : Sequence<T>
>S : S
>Sequence : Sequence<T>
>Tuple : Tuple<T, S>
>BinaryTuple : BinaryTuple<T, S>
>T : T
>S : S
}
Expand All @@ -47,14 +47,14 @@ interface List<T> extends Sequence<T> {
getLength(): number
>getLength : () => number

zip<S>(seq: Sequence<S>): List<Tuple<T, S>>
>zip : <S>(seq: Sequence<S>) => List<Tuple<T, S>>
zip<S>(seq: Sequence<S>): List<BinaryTuple<T, S>>
>zip : <S>(seq: Sequence<S>) => List<BinaryTuple<T, S>>
>S : S
>seq : Sequence<S>
>Sequence : Sequence<T>
>S : S
>List : List<T>
>Tuple : Tuple<T, S>
>BinaryTuple : BinaryTuple<T, S>
>T : T
>S : S
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"strict": true /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictTuples": true, /* Enable strict tuple checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictTuples": true, /* Enable strict tuple checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"strict": true /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictTuples": true, /* Enable strict tuple checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"strict": true /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictTuples": true, /* Enable strict tuple checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */

Expand Down
Loading

0 comments on commit 1f77317

Please sign in to comment.