From 9658b476c2fb012163c067d603a01fcd2b446f0d Mon Sep 17 00:00:00 2001
From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
Date: Wed, 25 Jul 2018 10:51:11 -0700
Subject: [PATCH] Fix inferFromUsage on index signatures (#25934)
* Fix inferFromUsage on index signatures
1. Check the argumentExpression to determine the index signature type.
Previously, the code mistakenly checked the type of the element access
itself, which never returned a good type.
2. If inference for the index signature type fails, substitute anyType.
Previously, the code would create a bad index signature with an
undefined type.
3. Add tests. Previously, there were no tests.
* Fixing (1) means that number index signatures are now created.
Previously, only string index signatures would be created.
* Fixing (2) means that index signatures will be inferred from single
usage like `return a[0]`. Previously, the refactoring would fail,
perhaps because of a check when stringifying the index signature (I
haven't tracked down why.)
* Update fourslash test with improved inference
---
src/services/codefixes/inferFromUsage.ts | 6 +++---
.../codeFixInferFromUsageNumberIndexSignature.ts | 8 ++++++++
.../codeFixInferFromUsageStringIndexSignature.ts | 8 ++++++++
tests/cases/fourslash/typeToStringCrashInCodeFix.ts | 4 ++--
4 files changed, 21 insertions(+), 5 deletions(-)
create mode 100644 tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts
create mode 100644 tests/cases/fourslash/codeFixInferFromUsageStringIndexSignature.ts
diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts
index 292b92dbd32..f7b5edc5ca7 100644
--- a/src/services/codefixes/inferFromUsage.ts
+++ b/src/services/codefixes/inferFromUsage.ts
@@ -501,7 +501,7 @@ namespace ts.codefix {
return;
}
else {
- const indexType = checker.getTypeAtLocation(parent);
+ const indexType = checker.getTypeAtLocation(parent.argumentExpression);
const indexUsageContext = {};
inferTypeFromContext(parent, checker, indexUsageContext);
if (indexType.flags & TypeFlags.NumberLike) {
@@ -562,11 +562,11 @@ namespace ts.codefix {
}
if (usageContext.numberIndexContext) {
- numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker)!, /*isReadonly*/ false); // TODO: GH#18217
+ numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker) || checker.getAnyType(), /*isReadonly*/ false);
}
if (usageContext.stringIndexContext) {
- stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker)!, /*isReadonly*/ false);
+ stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker) || checker.getAnyType(), /*isReadonly*/ false);
}
return checker.createAnonymousType(/*symbol*/ undefined!, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217
diff --git a/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts b/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts
new file mode 100644
index 00000000000..cf031bd017f
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInferFromUsageNumberIndexSignature.ts
@@ -0,0 +1,8 @@
+///
+
+// @noImplicitAny: true
+////function f([|a |]) {
+//// return a[0] + 1;
+////}
+
+verify.rangeAfterCodeFix("a: { [x: number]: number; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
diff --git a/tests/cases/fourslash/codeFixInferFromUsageStringIndexSignature.ts b/tests/cases/fourslash/codeFixInferFromUsageStringIndexSignature.ts
new file mode 100644
index 00000000000..765f788e054
--- /dev/null
+++ b/tests/cases/fourslash/codeFixInferFromUsageStringIndexSignature.ts
@@ -0,0 +1,8 @@
+///
+
+// @noImplicitAny: true
+////function f([|a |]) {
+//// return a['hi'];
+////}
+
+verify.rangeAfterCodeFix("a: { [x: string]: any; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);
diff --git a/tests/cases/fourslash/typeToStringCrashInCodeFix.ts b/tests/cases/fourslash/typeToStringCrashInCodeFix.ts
index 261f0824406..5201a6b77fb 100644
--- a/tests/cases/fourslash/typeToStringCrashInCodeFix.ts
+++ b/tests/cases/fourslash/typeToStringCrashInCodeFix.ts
@@ -1,6 +1,6 @@
///
// @noImplicitAny: true
-//// function f(y, z = { p: y[
+//// function f([|y |], z = { p: y[
-verify.not.codeFixAvailable();
+verify.rangeAfterCodeFix("y: { [x: string]: any; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);