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);