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
This commit is contained in:
Nathan Shively-Sanders 2018-07-25 10:51:11 -07:00 committed by GitHub
parent 7b4d13c95c
commit 9658b476c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 5 deletions

View File

@ -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

View File

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function f([|a |]) {
//// return a[0] + 1;
////}
verify.rangeAfterCodeFix("a: { [x: number]: number; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);

View File

@ -0,0 +1,8 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function f([|a |]) {
//// return a['hi'];
////}
verify.rangeAfterCodeFix("a: { [x: string]: any; }",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);

View File

@ -1,6 +1,6 @@
/// <reference path="fourslash.ts" />
// @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);