do not report 'noImplicitReturns' error if inferred return type of the function is void/any
This commit is contained in:
parent
2f282a786a
commit
d0e4a4ca92
5 changed files with 104 additions and 27 deletions
|
@ -9871,31 +9871,40 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
|
||||
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
|
||||
if (!returnType && !compilerOptions.noImplicitReturns) {
|
||||
if (returnType === voidType || isTypeAny(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
|
||||
// also if HasImplicitReturnValue flags is not set this means that all codepaths in function body end with return of throw
|
||||
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return of throw
|
||||
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
|
||||
if (compilerOptions.noImplicitReturns) {
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This function does not conform to the specification.
|
||||
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
|
||||
|
||||
if (returnType && !hasExplicitReturn) {
|
||||
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
|
||||
// this function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
|
||||
}
|
||||
else if (compilerOptions.noImplicitReturns){
|
||||
// errors in this branch should only be reported if CompilerOptions.noImplicitReturns flag is set
|
||||
if (!returnType) {
|
||||
// If return type annotation is omitted check if function has any explicit return statements.
|
||||
// If it does not have any - its inferred return type is void - don't do any checks.
|
||||
// Otherwise get inferred return type from function body and report error only if it is not void / anytype
|
||||
const inferredReturnType = hasExplicitReturn
|
||||
? getReturnTypeOfSignature(getSignatureFromDeclaration(func))
|
||||
: voidType;
|
||||
|
||||
if (inferredReturnType === voidType || isTypeAny(inferredReturnType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
|
||||
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
tests/cases/compiler/reachabilityChecks6.ts(6,10): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks6.ts(19,10): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks6.ts(31,10): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks6.ts(41,10): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks6.ts(52,10): error TS7030: Not all code paths return a value.
|
||||
|
@ -10,7 +9,7 @@ tests/cases/compiler/reachabilityChecks6.ts(116,10): error TS7030: Not all code
|
|||
tests/cases/compiler/reachabilityChecks6.ts(123,13): error TS7027: Unreachable code detected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/reachabilityChecks6.ts (10 errors) ====
|
||||
==== tests/cases/compiler/reachabilityChecks6.ts (9 errors) ====
|
||||
|
||||
function f0(x) {
|
||||
while (true);
|
||||
|
@ -32,8 +31,6 @@ tests/cases/compiler/reachabilityChecks6.ts(123,13): error TS7027: Unreachable c
|
|||
}
|
||||
|
||||
function f3(x) {
|
||||
~~
|
||||
!!! error TS7030: Not all code paths return a value.
|
||||
while (x) {
|
||||
throw new Error();
|
||||
}
|
||||
|
|
|
@ -1,21 +1,39 @@
|
|||
tests/cases/compiler/reachabilityChecks7.ts(3,16): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks7.ts(6,9): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks7.ts(14,16): error TS7030: Not all code paths return a value.
|
||||
tests/cases/compiler/reachabilityChecks7.ts(18,22): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
|
||||
|
||||
|
||||
==== tests/cases/compiler/reachabilityChecks7.ts (2 errors) ====
|
||||
|
||||
// async function without return type annotation - error
|
||||
async function f1() {
|
||||
~~
|
||||
!!! error TS7030: Not all code paths return a value.
|
||||
}
|
||||
|
||||
let x = async function() {
|
||||
~~~~~
|
||||
!!! error TS7030: Not all code paths return a value.
|
||||
}
|
||||
|
||||
// async function with which promised type is void - return can be omitted
|
||||
async function f2(): Promise<void> {
|
||||
|
||||
}
|
||||
|
||||
async function f3(x) {
|
||||
~~
|
||||
!!! error TS7030: Not all code paths return a value.
|
||||
if (x) return 10;
|
||||
}
|
||||
|
||||
async function f4(): Promise<number> {
|
||||
~~~~~~~~~~~~~~~
|
||||
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
|
||||
|
||||
}
|
||||
|
||||
function voidFunc(): void {
|
||||
}
|
||||
|
||||
function calltoVoidFunc(x) {
|
||||
if (x) return voidFunc();
|
||||
}
|
||||
|
||||
declare function use(s: string): void;
|
||||
let x1 = () => { use("Test"); }
|
|
@ -12,6 +12,24 @@ async function f2(): Promise<void> {
|
|||
|
||||
}
|
||||
|
||||
async function f3(x) {
|
||||
if (x) return 10;
|
||||
}
|
||||
|
||||
async function f4(): Promise<number> {
|
||||
|
||||
}
|
||||
|
||||
function voidFunc(): void {
|
||||
}
|
||||
|
||||
function calltoVoidFunc(x) {
|
||||
if (x) return voidFunc();
|
||||
}
|
||||
|
||||
declare function use(s: string): void;
|
||||
let x1 = () => { use("Test"); }
|
||||
|
||||
//// [reachabilityChecks7.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -40,3 +58,20 @@ function f2() {
|
|||
return __awaiter(this, void 0, Promise, function* () {
|
||||
});
|
||||
}
|
||||
function f3(x) {
|
||||
return __awaiter(this, void 0, Promise, function* () {
|
||||
if (x)
|
||||
return 10;
|
||||
});
|
||||
}
|
||||
function f4() {
|
||||
return __awaiter(this, void 0, Promise, function* () {
|
||||
});
|
||||
}
|
||||
function voidFunc() {
|
||||
}
|
||||
function calltoVoidFunc(x) {
|
||||
if (x)
|
||||
return voidFunc();
|
||||
}
|
||||
let x1 = () => { use("Test"); };
|
||||
|
|
|
@ -12,3 +12,21 @@ let x = async function() {
|
|||
async function f2(): Promise<void> {
|
||||
|
||||
}
|
||||
|
||||
async function f3(x) {
|
||||
if (x) return 10;
|
||||
}
|
||||
|
||||
async function f4(): Promise<number> {
|
||||
|
||||
}
|
||||
|
||||
function voidFunc(): void {
|
||||
}
|
||||
|
||||
function calltoVoidFunc(x) {
|
||||
if (x) return voidFunc();
|
||||
}
|
||||
|
||||
declare function use(s: string): void;
|
||||
let x1 = () => { use("Test"); }
|
Loading…
Reference in a new issue