diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 834228f7884..12a0aeff730 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -349,7 +349,7 @@ namespace ts.codefix { findChildOfKind>(containingFunction, SyntaxKind.ConstructorKeyword, sourceFile) : containingFunction.name; if (searchToken) { - return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken); + return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program, cancellationToken); } } } @@ -387,7 +387,8 @@ namespace ts.codefix { return getTypeFromUsageContext(usageContext, checker) || checker.getAnyType(); } - export function inferTypeForParametersFromReferences(references: ReadonlyArray, declaration: FunctionLikeDeclaration, checker: TypeChecker, cancellationToken: CancellationToken): ParameterInference[] | undefined { + export function inferTypeForParametersFromReferences(references: ReadonlyArray, declaration: FunctionLikeDeclaration, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined { + const checker = program.getTypeChecker(); if (references.length === 0) { return undefined; } @@ -422,10 +423,14 @@ namespace ts.codefix { types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex])); } } - if (!types.length) { - return { declaration: parameter, type: checker.getAnyType() }; + + let type = types.length && checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype)); + if ((!type || type.flags & TypeFlags.Any) && isIdentifier(parameter.name)) { + type = inferTypeForVariableFromUsage(parameter.name, program, cancellationToken); + } + if (!type) { + type = checker.getAnyType(); } - const type = checker.getWidenedType(checker.getUnionType(types, UnionReduction.Subtype)); return { type: isRest ? checker.createArrayType(type) : type, isOptional: isOptional && !isRest, diff --git a/tests/cases/fourslash/codeFixInferFromUsageCallBodyPriority.ts b/tests/cases/fourslash/codeFixInferFromUsageCallBodyPriority.ts new file mode 100644 index 00000000000..1603d35d742 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageCallBodyPriority.ts @@ -0,0 +1,18 @@ +/// +// based on acorn + +////function isIdentifierStart([|code, astral |]) { +//// if (code < 65) { return code === 36 } +//// if (code < 91) { return true } +//// if (code < 97) { return code === 95 } +//// if (code < 123) { return true } +//// if (code <= 0xffff) { return code >= 0xaa } +//// if (astral === false) { return false } +////} +//// +////function isLet(nextCh: any) { +//// return isIdentifierStart(nextCh, true) +////}; + + +verify.rangeAfterCodeFix("code: number, astral: boolean",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0);