Merge pull request #26292 from Kingwl/tupleIndexAccessCheck

check index access for fixed length tuple
This commit is contained in:
Ryan Cavanaugh 2018-09-05 12:10:46 -07:00 committed by GitHub
commit 6465e9dcdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 315 additions and 3 deletions

View file

@ -18498,6 +18498,13 @@ namespace ts {
error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
return errorType;
}
if (isTupleType(objectType) && !objectType.target.hasRestElement && isNumericLiteral(indexExpression)) {
const index = +indexExpression.text;
const maximumIndex = length(objectType.target.typeParameters);
if (index >= maximumIndex) {
error(indexExpression, Diagnostics.Index_0_is_out_of_bounds_in_tuple_of_length_1, index, maximumIndex);
}
}
return checkIndexedAccessIndexType(getIndexedAccessType(objectType, isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType, node), node);
}

View file

@ -2437,6 +2437,10 @@
"category": "Error",
"code": 2732
},
"Index '{0}' is out-of-bounds in tuple of length {1}.": {
"category": "Error",
"code": 2733
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View file

@ -0,0 +1,40 @@
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(22,13): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(23,13): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(24,13): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts(25,13): error TS2733: Index '3' is out-of-bounds in tuple of length 3.
==== tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple.ts (4 errors) ====
function f1(x: number): string { return "foo"; }
function f2(x: number): number { return 10; }
function f3(x: number): boolean { return true; }
enum E1 { one }
enum E2 { two }
var t1: [(x: number) => string, (x: number) => number];
var t2: [E1, E2];
var t3: [number, any];
var t4: [E1, E2, number];
// no error
t1 = [f1, f2];
t2 = [E1.one, E2.two];
t3 = [5, undefined];
t4 = [E1.one, E2.two, 20];
var e1 = t1[2]; // {}
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var e2 = t2[2]; // {}
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var e3 = t3[2]; // any
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var e4 = t4[3]; // number
~
!!! error TS2733: Index '3' is out-of-bounds in tuple of length 3.

View file

@ -0,0 +1,40 @@
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(17,14): error TS2733: Index '4' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(18,14): error TS2733: Index '4' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(19,14): error TS2733: Index '4' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(20,14): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts(21,14): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
==== tests/cases/conformance/types/typeRelationships/bestCommonType/bestCommonTypeOfTuple2.ts (5 errors) ====
interface base { }
interface base1 { i }
class C implements base { c }
class D implements base { d }
class E implements base { e }
class F extends C { f }
class C1 implements base1 { i = "foo"; c }
class D1 extends C1 { i = "bar"; d }
var t1: [C, base];
var t2: [C, D];
var t3: [C1, D1];
var t4: [base1, C1];
var t5: [C1, F]
var e11 = t1[4]; // base
~
!!! error TS2733: Index '4' is out-of-bounds in tuple of length 2.
var e21 = t2[4]; // {}
~
!!! error TS2733: Index '4' is out-of-bounds in tuple of length 2.
var e31 = t3[4]; // C1
~
!!! error TS2733: Index '4' is out-of-bounds in tuple of length 2.
var e41 = t4[2]; // base1
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var e51 = t5[2]; // {}
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.

View file

@ -6,6 +6,7 @@ tests/cases/conformance/types/tuple/castingTuple.ts(14,15): error TS2352: Conver
tests/cases/conformance/types/tuple/castingTuple.ts(15,14): error TS2352: Conversion of type '[number, string]' to type '[number, string, boolean]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
tests/cases/conformance/types/tuple/castingTuple.ts(18,21): error TS2352: Conversion of type '[C, D]' to type '[C, D, A]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Property '2' is missing in type '[C, D]'.
tests/cases/conformance/types/tuple/castingTuple.ts(20,33): error TS2733: Index '5' is out-of-bounds in tuple of length 3.
tests/cases/conformance/types/tuple/castingTuple.ts(30,10): error TS2352: Conversion of type '[number, string]' to type '[number, number]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'string' is not comparable to type 'number'.
tests/cases/conformance/types/tuple/castingTuple.ts(31,10): error TS2352: Conversion of type '[C, D]' to type '[A, I]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
@ -15,7 +16,7 @@ tests/cases/conformance/types/tuple/castingTuple.ts(32,5): error TS2403: Subsequ
tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot find name 't4'.
==== tests/cases/conformance/types/tuple/castingTuple.ts (8 errors) ====
==== tests/cases/conformance/types/tuple/castingTuple.ts (9 errors) ====
interface I { }
class A { a = 10; }
class C implements I { c };
@ -48,6 +49,8 @@ tests/cases/conformance/types/tuple/castingTuple.ts(33,1): error TS2304: Cannot
!!! error TS2352: Property '2' is missing in type '[C, D]'.
var eleFromCDA1 = classCDATuple[2]; // A
var eleFromCDA2 = classCDATuple[5]; // C | D | A
~
!!! error TS2733: Index '5' is out-of-bounds in tuple of length 3.
var t10: [E1, E2] = [E1.one, E2.one];
var t11 = <[number, number]>t10;
var array1 = <{}[]>emptyObjTuple;

View file

@ -0,0 +1,8 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts(2,11): error TS2733: Index '0' is out-of-bounds in tuple of length 0.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion01.ts (1 errors) ====
let x = <[]>[];
let y = x[0];
~
!!! error TS2733: Index '0' is out-of-bounds in tuple of length 0.

View file

@ -0,0 +1,8 @@
tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts(2,11): error TS2733: Index '0' is out-of-bounds in tuple of length 0.
==== tests/cases/conformance/types/tuple/emptyTuples/emptyTuplesTypeAssertion02.ts (1 errors) ====
let x = [] as [];
let y = x[0];
~
!!! error TS2733: Index '0' is out-of-bounds in tuple of length 0.

View file

@ -1,8 +1,11 @@
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(12,1): error TS2322: Type '[string, number, boolean, boolean]' is not assignable to type '[string, number]'.
Types of property 'length' are incompatible.
Type '4' is not assignable to type '2'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(13,20): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,1): error TS2322: Type '{ a: string; }' is not assignable to type 'string | number'.
Type '{ a: string; }' is not assignable to type 'number'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(14,11): error TS2733: Index '3' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(15,20): error TS2733: Index '3' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,14): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(22,17): error TS2322: Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts(23,14): error TS2322: Type '{}' is not assignable to type 'string'.
@ -11,7 +14,7 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup
Property '1' is missing in type '[{}]'.
==== tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts (7 errors) ====
==== tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTupleType.ts (10 errors) ====
interface I<T, U> {
tuple1: [T, U];
}
@ -29,11 +32,17 @@ tests/cases/conformance/types/typeRelationships/typeInference/genericCallWithTup
!!! error TS2322: Types of property 'length' are incompatible.
!!! error TS2322: Type '4' is not assignable to type '2'.
var e3 = i1.tuple1[2]; // {}
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
i1.tuple1[3] = { a: "string" };
~~~~~~~~~~~~
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'string | number'.
!!! error TS2322: Type '{ a: string; }' is not assignable to type 'number'.
~
!!! error TS2733: Index '3' is out-of-bounds in tuple of length 2.
var e4 = i1.tuple1[3]; // {}
~
!!! error TS2733: Index '3' is out-of-bounds in tuple of length 2.
i2.tuple1 = ["foo", 5];
i2.tuple1 = ["foo", "bar"];
i2.tuple1 = [5, "bar"];

View file

@ -0,0 +1,47 @@
tests/cases/conformance/types/tuple/indexerWithTuple.ts(11,25): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(17,27): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(20,30): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/tuple/indexerWithTuple.ts(28,30): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
==== tests/cases/conformance/types/tuple/indexerWithTuple.ts (4 errors) ====
var strNumTuple: [string, number] = ["foo", 10];
var numTupleTuple: [number, [string, number]] = [10, ["bar", 20]];
var unionTuple1: [number, string| number] = [10, "foo"];
var unionTuple2: [boolean, string| number] = [true, "foo"];
// no error
var idx0 = 0;
var idx1 = 1;
var ele10 = strNumTuple[0]; // string
var ele11 = strNumTuple[1]; // number
var ele12 = strNumTuple[2]; // string | number
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var ele13 = strNumTuple[idx0]; // string | number
var ele14 = strNumTuple[idx1]; // string | number
var ele15 = strNumTuple["0"]; // string
var ele16 = strNumTuple["1"]; // number
var strNumTuple1 = numTupleTuple[1]; //[string, number];
var ele17 = numTupleTuple[2]; // number | [string, number]
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var eleUnion10 = unionTuple1[0]; // number
var eleUnion11 = unionTuple1[1]; // string | number
var eleUnion12 = unionTuple1[2]; // string | number
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var eleUnion13 = unionTuple1[idx0]; // string | number
var eleUnion14 = unionTuple1[idx1]; // string | number
var eleUnion15 = unionTuple1["0"]; // number
var eleUnion16 = unionTuple1["1"]; // string | number
var eleUnion20 = unionTuple2[0]; // boolean
var eleUnion21 = unionTuple2[1]; // string | number
var eleUnion22 = unionTuple2[2]; // string | number | boolean
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var eleUnion23 = unionTuple2[idx0]; // string | number | boolean
var eleUnion24 = unionTuple2[idx1]; // string | number | boolean
var eleUnion25 = unionTuple2["0"]; // boolean
var eleUnion26 = unionTuple2["1"]; // string | number

View file

@ -0,0 +1,21 @@
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(5,14): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/conformance/types/tuple/tupleLengthCheck.ts(6,14): error TS2733: Index '1000' is out-of-bounds in tuple of length 2.
==== tests/cases/conformance/types/tuple/tupleLengthCheck.ts (2 errors) ====
declare const a: [number, string]
declare const rest: [number, string, ...boolean[]]
const a1 = a[1]
const a2 = a[2]
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
const a3 = a[1000]
~~~~
!!! error TS2733: Index '1000' is out-of-bounds in tuple of length 2.
const a4 = rest[1]
const a5 = rest[2]
const a6 = rest[3]
const a7 = rest[1000]

View file

@ -0,0 +1,22 @@
//// [tupleLengthCheck.ts]
declare const a: [number, string]
declare const rest: [number, string, ...boolean[]]
const a1 = a[1]
const a2 = a[2]
const a3 = a[1000]
const a4 = rest[1]
const a5 = rest[2]
const a6 = rest[3]
const a7 = rest[1000]
//// [tupleLengthCheck.js]
var a1 = a[1];
var a2 = a[2];
var a3 = a[1000];
var a4 = rest[1];
var a5 = rest[2];
var a6 = rest[3];
var a7 = rest[1000];

View file

@ -0,0 +1,37 @@
=== tests/cases/conformance/types/tuple/tupleLengthCheck.ts ===
declare const a: [number, string]
>a : Symbol(a, Decl(tupleLengthCheck.ts, 0, 13))
declare const rest: [number, string, ...boolean[]]
>rest : Symbol(rest, Decl(tupleLengthCheck.ts, 1, 13))
const a1 = a[1]
>a1 : Symbol(a1, Decl(tupleLengthCheck.ts, 3, 5))
>a : Symbol(a, Decl(tupleLengthCheck.ts, 0, 13))
>1 : Symbol(1)
const a2 = a[2]
>a2 : Symbol(a2, Decl(tupleLengthCheck.ts, 4, 5))
>a : Symbol(a, Decl(tupleLengthCheck.ts, 0, 13))
const a3 = a[1000]
>a3 : Symbol(a3, Decl(tupleLengthCheck.ts, 5, 5))
>a : Symbol(a, Decl(tupleLengthCheck.ts, 0, 13))
const a4 = rest[1]
>a4 : Symbol(a4, Decl(tupleLengthCheck.ts, 7, 5))
>rest : Symbol(rest, Decl(tupleLengthCheck.ts, 1, 13))
>1 : Symbol(1)
const a5 = rest[2]
>a5 : Symbol(a5, Decl(tupleLengthCheck.ts, 8, 5))
>rest : Symbol(rest, Decl(tupleLengthCheck.ts, 1, 13))
const a6 = rest[3]
>a6 : Symbol(a6, Decl(tupleLengthCheck.ts, 9, 5))
>rest : Symbol(rest, Decl(tupleLengthCheck.ts, 1, 13))
const a7 = rest[1000]
>a7 : Symbol(a7, Decl(tupleLengthCheck.ts, 10, 5))
>rest : Symbol(rest, Decl(tupleLengthCheck.ts, 1, 13))

View file

@ -0,0 +1,49 @@
=== tests/cases/conformance/types/tuple/tupleLengthCheck.ts ===
declare const a: [number, string]
>a : [number, string]
declare const rest: [number, string, ...boolean[]]
>rest : [number, string, ...boolean[]]
const a1 = a[1]
>a1 : string
>a[1] : string
>a : [number, string]
>1 : 1
const a2 = a[2]
>a2 : string | number
>a[2] : string | number
>a : [number, string]
>2 : 2
const a3 = a[1000]
>a3 : string | number
>a[1000] : string | number
>a : [number, string]
>1000 : 1000
const a4 = rest[1]
>a4 : string
>rest[1] : string
>rest : [number, string, ...boolean[]]
>1 : 1
const a5 = rest[2]
>a5 : boolean
>rest[2] : boolean
>rest : [number, string, ...boolean[]]
>2 : 2
const a6 = rest[3]
>a6 : boolean
>rest[3] : boolean
>rest : [number, string, ...boolean[]]
>3 : 3
const a7 = rest[1000]
>a7 : boolean
>rest[1000] : boolean
>rest : [number, string, ...boolean[]]
>1000 : 1000

View file

@ -1,3 +1,4 @@
tests/cases/compiler/tupleTypes.ts(11,12): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/compiler/tupleTypes.ts(14,1): error TS2322: Type '[]' is not assignable to type '[number, string]'.
Property '0' is missing in type '[]'.
tests/cases/compiler/tupleTypes.ts(15,1): error TS2322: Type '[number]' is not assignable to type '[number, string]'.
@ -7,6 +8,7 @@ tests/cases/compiler/tupleTypes.ts(17,15): error TS2322: Type 'number' is not as
tests/cases/compiler/tupleTypes.ts(18,1): error TS2322: Type '[number, string, number]' is not assignable to type '[number, string]'.
Types of property 'length' are incompatible.
Type '3' is not assignable to type '2'.
tests/cases/compiler/tupleTypes.ts(35,14): error TS2733: Index '2' is out-of-bounds in tuple of length 2.
tests/cases/compiler/tupleTypes.ts(41,1): error TS2322: Type '[]' is not assignable to type '[number, string]'.
tests/cases/compiler/tupleTypes.ts(47,1): error TS2322: Type '[number, string]' is not assignable to type 'number[]'.
Type 'string | number' is not assignable to type 'number'.
@ -20,7 +22,7 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
Type '{}' is not assignable to type 'string'.
==== tests/cases/compiler/tupleTypes.ts (10 errors) ====
==== tests/cases/compiler/tupleTypes.ts (12 errors) ====
var v1: []; // Error
var v2: [number];
var v3: [number, string];
@ -32,6 +34,8 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
var t1 = t[1]; // string
var t1: string;
var t2 = t[2]; // number|string
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var t2: number|string;
t = []; // Error
@ -70,6 +74,8 @@ tests/cases/compiler/tupleTypes.ts(51,1): error TS2322: Type '[number, {}]' is n
var tt1 = tt[1];
var tt1: string;
var tt2 = tt[2];
~
!!! error TS2733: Index '2' is out-of-bounds in tuple of length 2.
var tt2: number | string;
tt = tuple2(1, undefined);

View file

@ -0,0 +1,11 @@
declare const a: [number, string]
declare const rest: [number, string, ...boolean[]]
const a1 = a[1]
const a2 = a[2]
const a3 = a[1000]
const a4 = rest[1]
const a5 = rest[2]
const a6 = rest[3]
const a7 = rest[1000]