From 1d6863ab0b1f5530828be32240e31787282cd39f Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Sun, 13 Aug 2017 14:57:23 +0800 Subject: [PATCH 1/2] loosen number index check, fixes #15768 --- src/compiler/checker.ts | 13 ++++++------- tests/baselines/reference/genericNumberIndex.js | 5 +++++ .../baselines/reference/genericNumberIndex.symbols | 6 ++++++ tests/baselines/reference/genericNumberIndex.types | 6 ++++++ tests/cases/compiler/genericNumberIndex.ts | 1 + 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/genericNumberIndex.js create mode 100644 tests/baselines/reference/genericNumberIndex.symbols create mode 100644 tests/baselines/reference/genericNumberIndex.types create mode 100644 tests/cases/compiler/genericNumberIndex.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 903287707503c..a85332d3ded80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18758,13 +18758,12 @@ namespace ts { if (isTypeAssignableTo(indexType, getIndexType(objectType))) { return type; } - // Check if we're indexing with a numeric type and the object type is a generic - // type with a constraint that has a numeric index signature. - if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { - const constraint = getBaseConstraintOfType(objectType); - if (constraint && getIndexInfoOfType(constraint, IndexKind.Number)) { - return type; - } + // Check if we're indexing with a numeric type and if either object or index types + // is a generic type with a constraint that has a numeric index signature. + const typeOrConstraint = (tp: Type) => maybeTypeOfKind(tp, TypeFlags.TypeVariable) ? getBaseConstraintOfType(tp) || tp : tp; + if (isTypeAssignableToKind(typeOrConstraint(indexType), TypeFlags.NumberLike) && + getIndexInfoOfType(typeOrConstraint(objectType), IndexKind.Number)) { + return type; } error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); return type; diff --git a/tests/baselines/reference/genericNumberIndex.js b/tests/baselines/reference/genericNumberIndex.js new file mode 100644 index 0000000000000..c332d47001f87 --- /dev/null +++ b/tests/baselines/reference/genericNumberIndex.js @@ -0,0 +1,5 @@ +//// [genericNumberIndex.ts] +type X = ['a'][I]; + + +//// [genericNumberIndex.js] diff --git a/tests/baselines/reference/genericNumberIndex.symbols b/tests/baselines/reference/genericNumberIndex.symbols new file mode 100644 index 0000000000000..88a7f453390f1 --- /dev/null +++ b/tests/baselines/reference/genericNumberIndex.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/genericNumberIndex.ts === +type X = ['a'][I]; +>X : Symbol(X, Decl(genericNumberIndex.ts, 0, 0)) +>I : Symbol(I, Decl(genericNumberIndex.ts, 0, 7)) +>I : Symbol(I, Decl(genericNumberIndex.ts, 0, 7)) + diff --git a/tests/baselines/reference/genericNumberIndex.types b/tests/baselines/reference/genericNumberIndex.types new file mode 100644 index 0000000000000..36e9657a4c921 --- /dev/null +++ b/tests/baselines/reference/genericNumberIndex.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/genericNumberIndex.ts === +type X = ['a'][I]; +>X : ["a"][I] +>I : I +>I : I + diff --git a/tests/cases/compiler/genericNumberIndex.ts b/tests/cases/compiler/genericNumberIndex.ts new file mode 100644 index 0000000000000..c5aed2d474ec6 --- /dev/null +++ b/tests/cases/compiler/genericNumberIndex.ts @@ -0,0 +1 @@ +type X = ['a'][I]; From 4268e13cde69c1d8a48788ef91d3b16669076522 Mon Sep 17 00:00:00 2001 From: Tycho Grouwstra Date: Mon, 14 Aug 2017 17:45:18 +0800 Subject: [PATCH 2/2] simplify fix as suggested by @ahejlsberg --- src/compiler/checker.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a85332d3ded80..9b274c469567a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18760,9 +18760,7 @@ namespace ts { } // Check if we're indexing with a numeric type and if either object or index types // is a generic type with a constraint that has a numeric index signature. - const typeOrConstraint = (tp: Type) => maybeTypeOfKind(tp, TypeFlags.TypeVariable) ? getBaseConstraintOfType(tp) || tp : tp; - if (isTypeAssignableToKind(typeOrConstraint(indexType), TypeFlags.NumberLike) && - getIndexInfoOfType(typeOrConstraint(objectType), IndexKind.Number)) { + if (getIndexInfoOfType(getApparentType(objectType), IndexKind.Number) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { return type; } error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));