From 592b7cd30acc4fa9851b00a05a409b5ecaf490a0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:05:03 -0700 Subject: [PATCH 1/9] Explicit `undefined` return type checked similar to `void` return type --- src/compiler/checker.ts | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcf5c3854c960..48ec31a394db1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35425,10 +35425,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : neverType; // Normal function } if (types.length === 0) { - // For an async function, the return type will not be void, but rather a Promise for void. - return functionFlags & FunctionFlags.Async - ? createPromiseReturnType(func, voidType) // Async function - : voidType; // Normal function + // For an async function, the return type will not be void/undefined, but rather a Promise for void/undefined. + const contextualReturnType = getContextualReturnType(func, /*contextFlags*/ undefined); + const returnType = contextualReturnType && (unwrapReturnType(contextualReturnType, functionFlags) || voidType).flags & TypeFlags.Undefined ? undefinedType : voidType; + return functionFlags & FunctionFlags.Async ? createPromiseReturnType(func, returnType) : // Async function + returnType; // Normal function } // Return a union of the return expression types. @@ -35664,8 +35665,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const functionFlags = getFunctionFlags(func); const type = returnType && unwrapReturnType(returnType, functionFlags); - // Functions with an explicitly specified 'undefined, 'void', 'any' or 'unknown' return type don't need any return expressions. - if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any | TypeFlags.Unknown)) { + // Functions with an explicitly specified return type that includes `void` or is exactly `any` or `undefined` don't + // need any return statements. + if (type && (maybeTypeOfKind(type, TypeFlags.Void) || type.flags & (TypeFlags.Any | TypeFlags.Undefined))) { return; } @@ -35684,14 +35686,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (type && !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. - if (strictNullChecks) { - error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value); - } - else { - error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); - } + error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value); } - else if (type && strictNullChecks) { + else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { @@ -35703,7 +35700,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const inferredReturnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func)); - if (isUnwrappedReturnTypeVoidOrAny(func, inferredReturnType)) { + if (isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(func, inferredReturnType)) { return; } } @@ -42187,9 +42184,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isAsync ? getAwaitedTypeNoAlias(returnType) || errorType : returnType; } - function isUnwrappedReturnTypeVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean { + function isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(func: SignatureDeclaration, returnType: Type): boolean { const unwrappedReturnType = unwrapReturnType(returnType, getFunctionFlags(func)); - return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.AnyOrUnknown); + return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.AnyOrUnknown); } function checkReturnStatement(node: ReturnStatement) { @@ -42237,7 +42234,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) { + else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(container, returnType)) { // The function has a return type, but the return statement doesn't have an expression. error(node, Diagnostics.Not_all_code_paths_return_a_value); } From fccfd1effa8572ff8f150a3221ca132b2eb835d1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:05:21 -0700 Subject: [PATCH 2/9] Update error message --- src/compiler/diagnosticMessages.json | 6 +----- src/services/codefixes/returnValueCorrect.ts | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6ca4ec9e0941a..d48928639437a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1880,7 +1880,7 @@ "category": "Error", "code": 2354 }, - "A function whose declared type is neither 'void' nor 'any' must return a value.": { + "A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.": { "category": "Error", "code": 2355 }, @@ -3619,10 +3619,6 @@ "category": "Error", "code": 2846 }, - "A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.": { - "category": "Error", - "code": 2847 - }, "The right-hand side of an 'instanceof' expression must not be an instantiation expression.": { "category": "Error", "code": 2848 diff --git a/src/services/codefixes/returnValueCorrect.ts b/src/services/codefixes/returnValueCorrect.ts index fe9499d89d42b..2c16bfa5b2143 100644 --- a/src/services/codefixes/returnValueCorrect.ts +++ b/src/services/codefixes/returnValueCorrect.ts @@ -51,7 +51,6 @@ const fixIdAddReturnStatement = "fixAddReturnStatement"; const fixRemoveBracesFromArrowFunctionBody = "fixRemoveBracesFromArrowFunctionBody"; const fixIdWrapTheBlockWithParen = "fixWrapTheBlockWithParen"; const errorCodes = [ - Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value.code, Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value.code, Diagnostics.Type_0_is_not_assignable_to_type_1.code, Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code @@ -214,7 +213,6 @@ function getInfo(checker: TypeChecker, sourceFile: SourceFile, position: number, const declaration = findAncestor(node.parent, isFunctionLikeDeclaration); switch (errorCode) { - case Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value.code: case Diagnostics.A_function_whose_declared_type_is_neither_undefined_void_nor_any_must_return_a_value.code: if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) return undefined; return getFixInfo(checker, declaration, checker.getTypeFromTypeNode(declaration.type), /*isFunctionType*/ false); From f885333f8738d2ec1b75638eecaaa7dd90f2f163 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:05:51 -0700 Subject: [PATCH 3/9] Add/update tests --- ...nsMissingReturnStatementsAndExpressions.ts | 18 ++++++ ...tatementsAndExpressionsStrictNullChecks.ts | 58 ++++++++++++++++--- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts index cf5eb31ecad58..6ffb50c59a2f1 100644 --- a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts +++ b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts @@ -112,6 +112,24 @@ function f23(): undefined | number { // Error; because `undefined | number` becomes `number` without strictNullChecks. } +const f30: () => undefined = () => { + // Ok, contextual type for implicit return is `undefined` +} + +const f31: () => undefined = () => { + // Ok, contextual type for expression-less return is `undefined` + return; +} + +const f32: () => undefined | number = () => { + // Error, contextual type for implicit return isn't just `undefined` +} + +const f33: () => undefined | number = () => { + // Error, contextual type for expression-less return isn't just `undefined` + return; +} + class C { public get m1() { // Errors; get accessors must return a value. diff --git a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts index 89d3d5866221a..a43266bb2b75b 100644 --- a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts +++ b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts @@ -2,18 +2,60 @@ // @target: es2018 -function f1(): undefined | number { - // Okay; return type allows implicit return of undefined +function f10(): undefined { + // Ok, return type allows implicit return of undefined } -function f2(): number { - // Error; return type does not include undefined +function f11(): undefined | number { + // Error, return type isn't just undefined } -async function f3(): Promise { - // Okay; return type allows implicit return of undefined +function f12(): number { + // Error, return type doesn't include undefined } -async function f4(): Promise { - // Error; return type does not include undefined +const f20: () => undefined = () => { + // Ok, contextual type for implicit return is undefined } + +const f21: () => undefined | number = () => { + // Regular void function because contextual type for implicit return isn't just undefined +} + +const f22: () => number = () => { + // Regular void function because contextual type for implicit return isn't just undefined +} + +async function f30(): Promise { + // Ok, return type allows implicit return of undefined +} + +async function f31(): Promise { + // Error, return type isn't just undefined +} + +async function f32(): Promise { + // Error, return type doesn't include undefined +} + +// Examples from #36288 + +declare function f(a: () => undefined): void; + +f(() => { }); + +f((): undefined => { }); + +const g1: () => undefined = () => { }; + +const g2 = (): undefined => { }; + +function h1() { +} + +f(h1); // Error + +function h2(): undefined { +} + +f(h2); From fa57f3359f91829649cfa1d740eeabebecfdd79e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:12:44 -0700 Subject: [PATCH 4/9] Accept changes from updated error message --- .../reference/ParameterList5.errors.txt | 4 ++-- .../asyncFunctionDeclaration15_es5.errors.txt | 8 ++++---- .../asyncFunctionDeclaration15_es6.errors.txt | 8 ++++---- .../conflictingTypeAnnotatedVar.errors.txt | 8 ++++---- .../reference/controlFlowGenericTypes.errors.txt | 4 ++-- ...errorOnContextuallyTypedReturnType.errors.txt | 4 ++-- .../errorOnFunctionReturnType.errors.txt | 12 ++++++------ .../reference/invalidReturnStatements.errors.txt | 16 ++++++++-------- .../jsdocFunction_missingReturn.errors.txt | 4 ++-- .../jsdocOuterTypeParameters2.errors.txt | 4 ++-- .../reference/methodInAmbientClass1.errors.txt | 4 ++-- .../reference/missingReturnStatement.errors.txt | 4 ++-- .../reference/missingReturnStatement1.errors.txt | 4 ++-- .../reference/multiLineErrors.errors.txt | 4 ++-- .../parseInvalidNonNullableTypes.errors.txt | 8 ++++---- .../parserErrorRecovery_Block3.errors.txt | 8 ++++---- .../reference/parserParameterList5.errors.txt | 4 ++-- .../reference/reachabilityChecks5.errors.txt | 4 ++-- .../reference/reachabilityChecks7.errors.txt | 4 ++-- .../reference/recursiveFunctionTypes.errors.txt | 8 ++++---- .../reference/returnTypeParameter.errors.txt | 4 ++-- 21 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/baselines/reference/ParameterList5.errors.txt b/tests/baselines/reference/ParameterList5.errors.txt index 618ce74091527..f8479c8ab153f 100644 --- a/tests/baselines/reference/ParameterList5.errors.txt +++ b/tests/baselines/reference/ParameterList5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/ParameterList5.ts(1,15): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/ParameterList5.ts(1,15): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/ParameterList5.ts(1,16): error TS2369: A parameter property is only allowed in a constructor implementation. tests/cases/compiler/ParameterList5.ts(1,29): error TS2304: Cannot find name 'C'. @@ -6,7 +6,7 @@ tests/cases/compiler/ParameterList5.ts(1,29): error TS2304: Cannot find name 'C' ==== tests/cases/compiler/ParameterList5.ts (3 errors) ==== function A(): (public B) => C { ~~~~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt index 7e3595ec6f4e0..a325fc1fbb544 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration15_es5.errors.txt @@ -1,8 +1,8 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(6,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(7,23): error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. -tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(8,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(9,23): error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration15_es5.ts(10,23): error TS1055: Type 'typeof Thenable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. Construct signature return types 'Thenable' and 'PromiseLike' are incompatible. @@ -22,7 +22,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1 ~~~ !!! error TS1055: Type '{}' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. ~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. async function fn3(): any { } // error ~~~ !!! error TS1055: Type 'any' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. @@ -30,7 +30,7 @@ tests/cases/conformance/async/es5/functionDeclarations/asyncFunctionDeclaration1 ~~~~~~ !!! error TS1055: Type 'number' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. async function fn5(): PromiseLike { } // error ~~~~~~~~~~~~~~~~~ !!! error TS1055: Type 'PromiseLike' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. diff --git a/tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt b/tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt index 5b054a616893a..a4012f0a2a98a 100644 --- a/tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt +++ b/tests/baselines/reference/asyncFunctionDeclaration15_es6.errors.txt @@ -1,8 +1,8 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(6,23): error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise<{}>'? -tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(6,23): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(6,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(7,23): error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(8,23): error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? -tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(8,23): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(8,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(9,23): error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(10,23): error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(17,16): error TS1058: The return type of an async function must either be a valid promise or must not contain a callable 'then' member. @@ -19,7 +19,7 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1 ~~~ !!! error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise<{}>'? ~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. async function fn3(): any { } // error ~~~ !!! error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? @@ -27,7 +27,7 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1 ~~~~~~ !!! error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. async function fn5(): PromiseLike { } // error ~~~~~~~~~~~~~~~~~ !!! error TS1064: The return type of an async function or method must be the global Promise type. Did you mean to write 'Promise'? diff --git a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt index 2ab30ece7a080..25110800cfd01 100644 --- a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt +++ b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt @@ -1,10 +1,10 @@ tests/cases/compiler/conflictingTypeAnnotatedVar.ts(1,5): error TS2300: Duplicate identifier 'foo'. tests/cases/compiler/conflictingTypeAnnotatedVar.ts(2,10): error TS2300: Duplicate identifier 'foo'. tests/cases/compiler/conflictingTypeAnnotatedVar.ts(2,10): error TS2393: Duplicate function implementation. -tests/cases/compiler/conflictingTypeAnnotatedVar.ts(2,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/conflictingTypeAnnotatedVar.ts(2,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/conflictingTypeAnnotatedVar.ts(3,10): error TS2300: Duplicate identifier 'foo'. tests/cases/compiler/conflictingTypeAnnotatedVar.ts(3,10): error TS2393: Duplicate function implementation. -tests/cases/compiler/conflictingTypeAnnotatedVar.ts(3,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/conflictingTypeAnnotatedVar.ts(3,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (7 errors) ==== @@ -17,11 +17,11 @@ tests/cases/compiler/conflictingTypeAnnotatedVar.ts(3,17): error TS2355: A funct ~~~ !!! error TS2393: Duplicate function implementation. ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function foo(): number { } ~~~ !!! error TS2300: Duplicate identifier 'foo'. ~~~ !!! error TS2393: Duplicate function implementation. ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. \ No newline at end of file +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowGenericTypes.errors.txt b/tests/baselines/reference/controlFlowGenericTypes.errors.txt index 4686e36af6091..a0937290ca59d 100644 --- a/tests/baselines/reference/controlFlowGenericTypes.errors.txt +++ b/tests/baselines/reference/controlFlowGenericTypes.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(49,15): error TS2 tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(55,15): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'Box'. tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(81,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. Property 'foo' does not exist on type 'AA'. -tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(90,44): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(90,44): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(91,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'. Property 'foo' does not exist on type 'AA'. tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(156,16): error TS18048: 'obj' is possibly 'undefined'. @@ -109,7 +109,7 @@ tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(168,9): error TS1 const fn2 = (value: T): MyUnion => { ~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. value.foo; // Error ~~~ !!! error TS2339: Property 'foo' does not exist on type 'MyUnion'. diff --git a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt index 403e79b874271..a9a34aca2e004 100644 --- a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt +++ b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/errorOnContextuallyTypedReturnType.ts(1,5): error TS2322: Type '() => void' is not assignable to type '() => boolean'. Type 'void' is not assignable to type 'boolean'. -tests/cases/compiler/errorOnContextuallyTypedReturnType.ts(2,37): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/errorOnContextuallyTypedReturnType.ts(2,37): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (2 errors) ==== @@ -10,5 +10,5 @@ tests/cases/compiler/errorOnContextuallyTypedReturnType.ts(2,37): error TS2355: !!! error TS2322: Type 'void' is not assignable to type 'boolean'. var n2: () => boolean = function ():boolean { }; // expect an error here ~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. \ No newline at end of file diff --git a/tests/baselines/reference/errorOnFunctionReturnType.errors.txt b/tests/baselines/reference/errorOnFunctionReturnType.errors.txt index 4fa30fe7edf7f..1df3fd202020f 100644 --- a/tests/baselines/reference/errorOnFunctionReturnType.errors.txt +++ b/tests/baselines/reference/errorOnFunctionReturnType.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/jsdoc/foo.js(7,10): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/jsdoc/foo.js(7,10): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/jsdoc/foo.js(13,5): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/conformance/jsdoc/foo.js(16,60): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/conformance/jsdoc/foo.js(21,20): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/jsdoc/foo.js(16,60): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/conformance/jsdoc/foo.js(21,20): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/jsdoc/foo.js(31,10): error TS2534: A function returning 'never' cannot have a reachable end point. tests/cases/conformance/jsdoc/foo.js(37,5): error TS2322: Type 'string' is not assignable to type 'never'. tests/cases/conformance/jsdoc/foo.js(40,56): error TS2534: A function returning 'never' cannot have a reachable end point. @@ -17,7 +17,7 @@ tests/cases/conformance/jsdoc/foo.js(45,18): error TS2534: A function returning /** @type {FunctionReturningPromise} */ function testPromise1() { ~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. console.log("Nope"); } @@ -30,14 +30,14 @@ tests/cases/conformance/jsdoc/foo.js(45,18): error TS2534: A function returning var testPromise3 = /** @type {FunctionReturningPromise} */ function() { ~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. console.log("test") } /** @type {FunctionReturningPromise} */ var testPromise4 = function() { ~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. console.log("test") } diff --git a/tests/baselines/reference/invalidReturnStatements.errors.txt b/tests/baselines/reference/invalidReturnStatements.errors.txt index fe34106169bf6..b8e599da59ebe 100644 --- a/tests/baselines/reference/invalidReturnStatements.errors.txt +++ b/tests/baselines/reference/invalidReturnStatements.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(2,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(3,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(4,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(5,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(2,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(3,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(4,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(5,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(16,22): error TS2739: Type '{ id: number; }' is missing the following properties from type 'D': name, dispose tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(18,22): error TS2741: Property 'name' is missing in type 'C' but required in type 'D'. @@ -10,16 +10,16 @@ tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts(1 // all the following should be error function fn1(): number { } ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function fn2(): string { } ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function fn3(): boolean { } ~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function fn4(): Date { } ~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function fn7(): any { } // should be valid: any includes void interface I { id: number } diff --git a/tests/baselines/reference/jsdocFunction_missingReturn.errors.txt b/tests/baselines/reference/jsdocFunction_missingReturn.errors.txt index 8e102d797ec7c..8a201dc004f84 100644 --- a/tests/baselines/reference/jsdocFunction_missingReturn.errors.txt +++ b/tests/baselines/reference/jsdocFunction_missingReturn.errors.txt @@ -1,9 +1,9 @@ -/a.js(1,24): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +/a.js(1,24): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== /a.js (1 errors) ==== /** @type {function(): number} */ ~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function f() {} \ No newline at end of file diff --git a/tests/baselines/reference/jsdocOuterTypeParameters2.errors.txt b/tests/baselines/reference/jsdocOuterTypeParameters2.errors.txt index a0a53680b66db..239d6d641bb1b 100644 --- a/tests/baselines/reference/jsdocOuterTypeParameters2.errors.txt +++ b/tests/baselines/reference/jsdocOuterTypeParameters2.errors.txt @@ -1,6 +1,6 @@ error TS5055: Cannot write file 'tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js' because it would overwrite input file. Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig. -tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(1,14): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(1,14): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(7,35): error TS2339: Property 'foo' does not exist on type 'Bar'. @@ -9,7 +9,7 @@ tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js(7,35): error TS2339: ==== tests/cases/conformance/jsdoc/jsdocOuterTypeParameters1.js (2 errors) ==== /** @return {T} */ ~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. const dedupingMixin = function(mixin) {}; /** @template T */ diff --git a/tests/baselines/reference/methodInAmbientClass1.errors.txt b/tests/baselines/reference/methodInAmbientClass1.errors.txt index c931cc0101c81..30c3b028e28c9 100644 --- a/tests/baselines/reference/methodInAmbientClass1.errors.txt +++ b/tests/baselines/reference/methodInAmbientClass1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/methodInAmbientClass1.ts(2,12): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/methodInAmbientClass1.ts(2,12): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/methodInAmbientClass1.ts(2,20): error TS1183: An implementation cannot be declared in ambient contexts. @@ -6,7 +6,7 @@ tests/cases/compiler/methodInAmbientClass1.ts(2,20): error TS1183: An implementa declare class Foo { fn(): boolean { ~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ~ !!! error TS1183: An implementation cannot be declared in ambient contexts. } diff --git a/tests/baselines/reference/missingReturnStatement.errors.txt b/tests/baselines/reference/missingReturnStatement.errors.txt index 8926d22be3d42..65b210959c366 100644 --- a/tests/baselines/reference/missingReturnStatement.errors.txt +++ b/tests/baselines/reference/missingReturnStatement.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/missingReturnStatement.ts(3,22): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/missingReturnStatement.ts(3,22): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/compiler/missingReturnStatement.ts (1 errors) ==== @@ -6,7 +6,7 @@ tests/cases/compiler/missingReturnStatement.ts(3,22): error TS2355: A function w export class Bug { public foo():string { ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } } } diff --git a/tests/baselines/reference/missingReturnStatement1.errors.txt b/tests/baselines/reference/missingReturnStatement1.errors.txt index 9d3cf78411edf..362ccae2439e2 100644 --- a/tests/baselines/reference/missingReturnStatement1.errors.txt +++ b/tests/baselines/reference/missingReturnStatement1.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/missingReturnStatement1.ts(2,12): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/missingReturnStatement1.ts(2,12): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/compiler/missingReturnStatement1.ts (1 errors) ==== class Foo { foo(): number { ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. //return 4; } } diff --git a/tests/baselines/reference/multiLineErrors.errors.txt b/tests/baselines/reference/multiLineErrors.errors.txt index 851425baef434..22818f974cdf2 100644 --- a/tests/baselines/reference/multiLineErrors.errors.txt +++ b/tests/baselines/reference/multiLineErrors.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/multiLineErrors.ts(3,22): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/multiLineErrors.ts(3,22): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/multiLineErrors.ts(21,1): error TS2322: Type 'A2' is not assignable to type 'A1'. The types of 'x.y' are incompatible between these types. Type 'string' is not assignable to type 'number'. @@ -15,7 +15,7 @@ tests/cases/compiler/multiLineErrors.ts(21,1): error TS2322: Type 'A2' is not as ~~~~~~~~~~~~~~ } ~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. { var x = 4; var y = 10; diff --git a/tests/baselines/reference/parseInvalidNonNullableTypes.errors.txt b/tests/baselines/reference/parseInvalidNonNullableTypes.errors.txt index 378419d288544..e8df20fe40570 100644 --- a/tests/baselines/reference/parseInvalidNonNullableTypes.errors.txt +++ b/tests/baselines/reference/parseInvalidNonNullableTypes.errors.txt @@ -4,9 +4,9 @@ tests/cases/compiler/parseInvalidNonNullableTypes.ts(9,16): error TS17019: '!' a tests/cases/compiler/parseInvalidNonNullableTypes.ts(10,16): error TS17019: '!' at the end of a type is not valid TypeScript syntax. Did you mean to write 'number'? tests/cases/compiler/parseInvalidNonNullableTypes.ts(12,16): error TS17020: '!' at the start of a type is not valid TypeScript syntax. Did you mean to write 'string'? tests/cases/compiler/parseInvalidNonNullableTypes.ts(13,16): error TS17020: '!' at the start of a type is not valid TypeScript syntax. Did you mean to write 'number'? -tests/cases/compiler/parseInvalidNonNullableTypes.ts(15,16): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/parseInvalidNonNullableTypes.ts(15,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/parseInvalidNonNullableTypes.ts(15,16): error TS17019: '!' at the end of a type is not valid TypeScript syntax. Did you mean to write 'string'? -tests/cases/compiler/parseInvalidNonNullableTypes.ts(16,16): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/parseInvalidNonNullableTypes.ts(16,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/parseInvalidNonNullableTypes.ts(16,16): error TS17020: '!' at the start of a type is not valid TypeScript syntax. Did you mean to write 'string'? tests/cases/compiler/parseInvalidNonNullableTypes.ts(18,16): error TS17019: '!' at the end of a type is not valid TypeScript syntax. Did you mean to write 'any'? tests/cases/compiler/parseInvalidNonNullableTypes.ts(19,10): error TS17019: '!' at the end of a type is not valid TypeScript syntax. Did you mean to write 'number'? @@ -43,12 +43,12 @@ tests/cases/compiler/parseInvalidNonNullableTypes.ts(22,10): error TS17020: '!' function f7(): string! {} ~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ~~~~~~~ !!! error TS17019: '!' at the end of a type is not valid TypeScript syntax. Did you mean to write 'string'? function f8(): !string {} ~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ~~~~~~~ !!! error TS17020: '!' at the start of a type is not valid TypeScript syntax. Did you mean to write 'string'? diff --git a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt index e6033d05215d9..d1825b0edef26 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt @@ -1,18 +1,18 @@ -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts(2,18): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts(2,18): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts(4,5): error TS1128: Declaration or statement expected. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts(4,18): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts(4,18): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts (3 errors) ==== class C { private a(): boolean { ~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. private b(): boolean { ~~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList5.errors.txt b/tests/baselines/reference/parserParameterList5.errors.txt index 5f0899fa1a2a6..43693ef1da355 100644 --- a/tests/baselines/reference/parserParameterList5.errors.txt +++ b/tests/baselines/reference/parserParameterList5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts(1,15): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts(1,15): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts(1,16): error TS2369: A parameter property is only allowed in a constructor implementation. tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts(1,29): error TS2304: Cannot find name 'C'. @@ -6,7 +6,7 @@ tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.t ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts (3 errors) ==== function A(): (public B) => C { ~~~~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ~~~~~~~~ !!! error TS2369: A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/reachabilityChecks5.errors.txt b/tests/baselines/reference/reachabilityChecks5.errors.txt index f8c7e6f4dbc1a..039d9c2bbc592 100644 --- a/tests/baselines/reference/reachabilityChecks5.errors.txt +++ b/tests/baselines/reference/reachabilityChecks5.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/reachabilityChecks5.ts(5,17): error TS7030: Not all code paths return a value. -tests/cases/compiler/reachabilityChecks5.ts(18,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/reachabilityChecks5.ts(18,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/reachabilityChecks5.ts(30,17): error TS7030: Not all code paths return a value. tests/cases/compiler/reachabilityChecks5.ts(40,17): error TS7030: Not all code paths return a value. tests/cases/compiler/reachabilityChecks5.ts(51,17): error TS7030: Not all code paths return a value. @@ -33,7 +33,7 @@ tests/cases/compiler/reachabilityChecks5.ts(122,13): error TS7027: Unreachable c function f3(x): number { ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. while (x) { throw new Error(); } diff --git a/tests/baselines/reference/reachabilityChecks7.errors.txt b/tests/baselines/reference/reachabilityChecks7.errors.txt index 9ac2d0c1ad8ae..a1985d0dab079 100644 --- a/tests/baselines/reference/reachabilityChecks7.errors.txt +++ b/tests/baselines/reference/reachabilityChecks7.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/reachabilityChecks7.ts(13,16): error TS7030: Not all code paths return a value. -tests/cases/compiler/reachabilityChecks7.ts(17,22): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/reachabilityChecks7.ts(17,22): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. ==== tests/cases/compiler/reachabilityChecks7.ts (2 errors) ==== @@ -23,7 +23,7 @@ tests/cases/compiler/reachabilityChecks7.ts(17,22): error TS2355: A function who async function f4(): Promise { ~~~~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } diff --git a/tests/baselines/reference/recursiveFunctionTypes.errors.txt b/tests/baselines/reference/recursiveFunctionTypes.errors.txt index 13ab49c4666ec..a624048495993 100644 --- a/tests/baselines/reference/recursiveFunctionTypes.errors.txt +++ b/tests/baselines/reference/recursiveFunctionTypes.errors.txt @@ -2,8 +2,8 @@ tests/cases/compiler/recursiveFunctionTypes.ts(1,28): error TS2322: Type 'number tests/cases/compiler/recursiveFunctionTypes.ts(3,5): error TS2322: Type '() => typeof fn' is not assignable to type 'number'. tests/cases/compiler/recursiveFunctionTypes.ts(4,5): error TS2322: Type '() => typeof fn' is not assignable to type '() => number'. Type '() => typeof fn' is not assignable to type 'number'. -tests/cases/compiler/recursiveFunctionTypes.ts(11,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/compiler/recursiveFunctionTypes.ts(12,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/recursiveFunctionTypes.ts(11,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/recursiveFunctionTypes.ts(12,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/recursiveFunctionTypes.ts(17,5): error TS2322: Type '() => I' is not assignable to type 'number'. tests/cases/compiler/recursiveFunctionTypes.ts(22,5): error TS2345: Argument of type 'number' is not assignable to parameter of type '(t: typeof g) => void'. tests/cases/compiler/recursiveFunctionTypes.ts(25,1): error TS2322: Type 'number' is not assignable to type '() => any'. @@ -40,10 +40,10 @@ tests/cases/compiler/recursiveFunctionTypes.ts(43,4): error TS2769: No overload function f2(): typeof g2 { } ~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function g2(): typeof f2 { } ~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. interface I { } function f3(): I { return f3; } diff --git a/tests/baselines/reference/returnTypeParameter.errors.txt b/tests/baselines/reference/returnTypeParameter.errors.txt index 24b9e725de8fd..6cbd483a4fd36 100644 --- a/tests/baselines/reference/returnTypeParameter.errors.txt +++ b/tests/baselines/reference/returnTypeParameter.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/returnTypeParameter.ts(1,22): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/compiler/returnTypeParameter.ts(1,22): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/compiler/returnTypeParameter.ts(2,34): error TS2693: 'T' only refers to a type, but is being used as a value here. ==== tests/cases/compiler/returnTypeParameter.ts (2 errors) ==== function f(a: T): T { } // error, no return statement ~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. function f2(a: T): T { return T; } // bug was that this satisfied the return statement requirement ~ !!! error TS2693: 'T' only refers to a type, but is being used as a value here. \ No newline at end of file From edd66e5033eadeb618053dfa12adcd20d57bafcf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:13:12 -0700 Subject: [PATCH 5/9] Accept changes from updated error message --- .../reference/functionImplementationErrors.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index cdd16bc902718..bf4103f01bf98 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it. tests/cases/conformance/functions/functionImplementationErrors.ts(40,1): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value. @@ -31,7 +31,7 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(40,1): error T // Function implemetnation with non -void return type annotation with no return function f5(): number { ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } var m; From 39ed3b883d2ddc0cc02accf7e38ebd1ac329d850 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 31 Mar 2023 09:13:40 -0700 Subject: [PATCH 6/9] Accept changes from new tests --- ...gReturnStatementsAndExpressions.errors.txt | 48 +++++++-- ...nsMissingReturnStatementsAndExpressions.js | 32 ++++++ ...singReturnStatementsAndExpressions.symbols | 38 +++++-- ...issingReturnStatementsAndExpressions.types | 30 ++++++ ...sAndExpressionsStrictNullChecks.errors.txt | 93 ++++++++++++++--- ...tatementsAndExpressionsStrictNullChecks.js | 99 ++++++++++++++++--- ...entsAndExpressionsStrictNullChecks.symbols | 89 ++++++++++++++--- ...ementsAndExpressionsStrictNullChecks.types | 99 ++++++++++++++++--- .../reference/unknownType1.errors.txt | 5 +- 9 files changed, 461 insertions(+), 72 deletions(-) diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt index f4466e0b869e4..e89e11b90c821 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt @@ -1,15 +1,19 @@ -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(1,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(99,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(107,17): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(112,16): error TS2378: A 'get' accessor must return a value. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(134,15): error TS18050: The value 'undefined' cannot be used here. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(135,5): error TS1003: Identifier expected. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(1,16): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(99,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(107,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(120,7): error TS2322: Type '() => void' is not assignable to type '() => number'. + Type 'void' is not assignable to type 'number'. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(124,7): error TS2322: Type '() => void' is not assignable to type '() => number'. + Type 'void' is not assignable to type 'number'. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(130,16): error TS2378: A 'get' accessor must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(152,15): error TS18050: The value 'undefined' cannot be used here. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(153,5): error TS1003: Identifier expected. -==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (6 errors) ==== +==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (8 errors) ==== function f1(): string { ~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. // errors because there are no return statements } @@ -109,7 +113,7 @@ tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(135,5): e function f21(): number | string { ~~~~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. // Not okay; union does not contain void or any } @@ -119,10 +123,34 @@ tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts(135,5): e function f23(): undefined | number { ~~~~~~~~~~~~~~~~~~ -!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. // Error; because `undefined | number` becomes `number` without strictNullChecks. } + const f30: () => undefined = () => { + // Ok, contextual type for implicit return is `undefined` + } + + const f31: () => undefined = () => { + // Ok, contextual type for expression-less return is `undefined` + return; + } + + const f32: () => undefined | number = () => { + ~~~ +!!! error TS2322: Type '() => void' is not assignable to type '() => number'. +!!! error TS2322: Type 'void' is not assignable to type 'number'. + // Error, contextual type for implicit return isn't just `undefined` + } + + const f33: () => undefined | number = () => { + ~~~ +!!! error TS2322: Type '() => void' is not assignable to type '() => number'. +!!! error TS2322: Type 'void' is not assignable to type 'number'. + // Error, contextual type for expression-less return isn't just `undefined` + return; + } + class C { public get m1() { ~~ diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.js b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.js index 4cc59397c5e06..bebeb24af0a28 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.js +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.js @@ -109,6 +109,24 @@ function f23(): undefined | number { // Error; because `undefined | number` becomes `number` without strictNullChecks. } +const f30: () => undefined = () => { + // Ok, contextual type for implicit return is `undefined` +} + +const f31: () => undefined = () => { + // Ok, contextual type for expression-less return is `undefined` + return; +} + +const f32: () => undefined | number = () => { + // Error, contextual type for implicit return isn't just `undefined` +} + +const f33: () => undefined | number = () => { + // Error, contextual type for expression-less return isn't just `undefined` + return; +} + class C { public get m1() { // Errors; get accessors must return a value. @@ -224,6 +242,20 @@ function f22() { function f23() { // Error; because `undefined | number` becomes `number` without strictNullChecks. } +var f30 = function () { + // Ok, contextual type for implicit return is `undefined` +}; +var f31 = function () { + // Ok, contextual type for expression-less return is `undefined` + return; +}; +var f32 = function () { + // Error, contextual type for implicit return isn't just `undefined` +}; +var f33 = function () { + // Error, contextual type for expression-less return isn't just `undefined` + return; +}; var C = /** @class */ (function () { function C() { } diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.symbols b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.symbols index c7048ff46c778..9df5be73abadb 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.symbols +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.symbols @@ -164,37 +164,63 @@ function f23(): undefined | number { // Error; because `undefined | number` becomes `number` without strictNullChecks. } +const f30: () => undefined = () => { +>f30 : Symbol(f30, Decl(functionsMissingReturnStatementsAndExpressions.ts, 110, 5)) + + // Ok, contextual type for implicit return is `undefined` +} + +const f31: () => undefined = () => { +>f31 : Symbol(f31, Decl(functionsMissingReturnStatementsAndExpressions.ts, 114, 5)) + + // Ok, contextual type for expression-less return is `undefined` + return; +} + +const f32: () => undefined | number = () => { +>f32 : Symbol(f32, Decl(functionsMissingReturnStatementsAndExpressions.ts, 119, 5)) + + // Error, contextual type for implicit return isn't just `undefined` +} + +const f33: () => undefined | number = () => { +>f33 : Symbol(f33, Decl(functionsMissingReturnStatementsAndExpressions.ts, 123, 5)) + + // Error, contextual type for expression-less return isn't just `undefined` + return; +} + class C { ->C : Symbol(C, Decl(functionsMissingReturnStatementsAndExpressions.ts, 108, 1)) +>C : Symbol(C, Decl(functionsMissingReturnStatementsAndExpressions.ts, 126, 1)) public get m1() { ->m1 : Symbol(C.m1, Decl(functionsMissingReturnStatementsAndExpressions.ts, 110, 9)) +>m1 : Symbol(C.m1, Decl(functionsMissingReturnStatementsAndExpressions.ts, 128, 9)) // Errors; get accessors must return a value. } public get m2() { ->m2 : Symbol(C.m2, Decl(functionsMissingReturnStatementsAndExpressions.ts, 113, 5)) +>m2 : Symbol(C.m2, Decl(functionsMissingReturnStatementsAndExpressions.ts, 131, 5)) // Permissible; returns undefined. return; } public get m3() { ->m3 : Symbol(C.m3, Decl(functionsMissingReturnStatementsAndExpressions.ts, 118, 5)) +>m3 : Symbol(C.m3, Decl(functionsMissingReturnStatementsAndExpressions.ts, 136, 5)) return "Okay, because this is a return expression."; } public get m4() { ->m4 : Symbol(C.m4, Decl(functionsMissingReturnStatementsAndExpressions.ts, 122, 5)) +>m4 : Symbol(C.m4, Decl(functionsMissingReturnStatementsAndExpressions.ts, 140, 5)) // Fine since this consists of a single throw statement. throw null; } public get m5() { ->m5 : Symbol(C.m5, Decl(functionsMissingReturnStatementsAndExpressions.ts, 127, 5)) +>m5 : Symbol(C.m5, Decl(functionsMissingReturnStatementsAndExpressions.ts, 145, 5)) // Not fine, since we can *only* consist of a single throw statement // if no return statements are present but we are a get accessor. diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.types b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.types index 5e6b014bfa2d6..39b4fdd7faa98 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.types +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.types @@ -166,6 +166,36 @@ function f23(): undefined | number { // Error; because `undefined | number` becomes `number` without strictNullChecks. } +const f30: () => undefined = () => { +>f30 : () => undefined +>() => { // Ok, contextual type for implicit return is `undefined`} : () => undefined + + // Ok, contextual type for implicit return is `undefined` +} + +const f31: () => undefined = () => { +>f31 : () => undefined +>() => { // Ok, contextual type for expression-less return is `undefined` return;} : () => undefined + + // Ok, contextual type for expression-less return is `undefined` + return; +} + +const f32: () => undefined | number = () => { +>f32 : () => undefined | number +>() => { // Error, contextual type for implicit return isn't just `undefined`} : () => void + + // Error, contextual type for implicit return isn't just `undefined` +} + +const f33: () => undefined | number = () => { +>f33 : () => undefined | number +>() => { // Error, contextual type for expression-less return isn't just `undefined` return;} : () => void + + // Error, contextual type for expression-less return isn't just `undefined` + return; +} + class C { >C : C diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt index a570470cf2ea0..dccad1eccf8e6 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt @@ -1,25 +1,88 @@ -tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(5,16): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. -tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(13,22): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(5,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(9,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(17,7): error TS2322: Type '() => void' is not assignable to type '() => number | undefined'. + Type 'void' is not assignable to type 'number | undefined'. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(21,7): error TS2322: Type '() => void' is not assignable to type '() => number'. + Type 'void' is not assignable to type 'number'. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(29,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(33,23): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts(52,3): error TS2345: Argument of type '() => void' is not assignable to parameter of type '() => undefined'. + Type 'void' is not assignable to type 'undefined'. -==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts (2 errors) ==== - function f1(): undefined | number { - // Okay; return type allows implicit return of undefined +==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts (7 errors) ==== + function f10(): undefined { + // Ok, return type allows implicit return of undefined } - function f2(): number { - ~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. - // Error; return type does not include undefined + function f11(): undefined | number { + ~~~~~~~~~~~~~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + // Error, return type isn't just undefined } - async function f3(): Promise { - // Okay; return type allows implicit return of undefined + function f12(): number { + ~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + // Error, return type doesn't include undefined } - async function f4(): Promise { - ~~~~~~~~~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. - // Error; return type does not include undefined + const f20: () => undefined = () => { + // Ok, contextual type for implicit return is undefined } + + const f21: () => undefined | number = () => { + ~~~ +!!! error TS2322: Type '() => void' is not assignable to type '() => number | undefined'. +!!! error TS2322: Type 'void' is not assignable to type 'number | undefined'. + // Regular void function because contextual type for implicit return isn't just undefined + } + + const f22: () => number = () => { + ~~~ +!!! error TS2322: Type '() => void' is not assignable to type '() => number'. +!!! error TS2322: Type 'void' is not assignable to type 'number'. + // Regular void function because contextual type for implicit return isn't just undefined + } + + async function f30(): Promise { + // Ok, return type allows implicit return of undefined + } + + async function f31(): Promise { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + // Error, return type isn't just undefined + } + + async function f32(): Promise { + ~~~~~~~~~~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + // Error, return type doesn't include undefined + } + + // Examples from #36288 + + declare function f(a: () => undefined): void; + + f(() => { }); + + f((): undefined => { }); + + const g1: () => undefined = () => { }; + + const g2 = (): undefined => { }; + + function h1() { + } + + f(h1); // Error + ~~ +!!! error TS2345: Argument of type '() => void' is not assignable to parameter of type '() => undefined'. +!!! error TS2345: Type 'void' is not assignable to type 'undefined'. + + function h2(): undefined { + } + + f(h2); \ No newline at end of file diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js index 3ca9a8cc8353d..99801b800481d 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js @@ -1,31 +1,98 @@ //// [functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts] -function f1(): undefined | number { - // Okay; return type allows implicit return of undefined +function f10(): undefined { + // Ok, return type allows implicit return of undefined } -function f2(): number { - // Error; return type does not include undefined +function f11(): undefined | number { + // Error, return type isn't just undefined } -async function f3(): Promise { - // Okay; return type allows implicit return of undefined +function f12(): number { + // Error, return type doesn't include undefined } -async function f4(): Promise { - // Error; return type does not include undefined +const f20: () => undefined = () => { + // Ok, contextual type for implicit return is undefined } + +const f21: () => undefined | number = () => { + // Regular void function because contextual type for implicit return isn't just undefined +} + +const f22: () => number = () => { + // Regular void function because contextual type for implicit return isn't just undefined +} + +async function f30(): Promise { + // Ok, return type allows implicit return of undefined +} + +async function f31(): Promise { + // Error, return type isn't just undefined +} + +async function f32(): Promise { + // Error, return type doesn't include undefined +} + +// Examples from #36288 + +declare function f(a: () => undefined): void; + +f(() => { }); + +f((): undefined => { }); + +const g1: () => undefined = () => { }; + +const g2 = (): undefined => { }; + +function h1() { +} + +f(h1); // Error + +function h2(): undefined { +} + +f(h2); //// [functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js] -function f1() { - // Okay; return type allows implicit return of undefined +function f10() { + // Ok, return type allows implicit return of undefined +} +function f11() { + // Error, return type isn't just undefined +} +function f12() { + // Error, return type doesn't include undefined +} +const f20 = () => { + // Ok, contextual type for implicit return is undefined +}; +const f21 = () => { + // Regular void function because contextual type for implicit return isn't just undefined +}; +const f22 = () => { + // Regular void function because contextual type for implicit return isn't just undefined +}; +async function f30() { + // Ok, return type allows implicit return of undefined +} +async function f31() { + // Error, return type isn't just undefined } -function f2() { - // Error; return type does not include undefined +async function f32() { + // Error, return type doesn't include undefined } -async function f3() { - // Okay; return type allows implicit return of undefined +f(() => { }); +f(() => { }); +const g1 = () => { }; +const g2 = () => { }; +function h1() { } -async function f4() { - // Error; return type does not include undefined +f(h1); // Error +function h2() { } +f(h2); diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols index befceb738b18a..121cf61a005fb 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols @@ -1,27 +1,92 @@ === tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts === -function f1(): undefined | number { ->f1 : Symbol(f1, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 0, 0)) +function f10(): undefined { +>f10 : Symbol(f10, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 0, 0)) - // Okay; return type allows implicit return of undefined + // Ok, return type allows implicit return of undefined } -function f2(): number { ->f2 : Symbol(f2, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 2, 1)) +function f11(): undefined | number { +>f11 : Symbol(f11, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 2, 1)) - // Error; return type does not include undefined + // Error, return type isn't just undefined } -async function f3(): Promise { ->f3 : Symbol(f3, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 6, 1)) +function f12(): number { +>f12 : Symbol(f12, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 6, 1)) + + // Error, return type doesn't include undefined +} + +const f20: () => undefined = () => { +>f20 : Symbol(f20, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 12, 5)) + + // Ok, contextual type for implicit return is undefined +} + +const f21: () => undefined | number = () => { +>f21 : Symbol(f21, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 16, 5)) + + // Regular void function because contextual type for implicit return isn't just undefined +} + +const f22: () => number = () => { +>f22 : Symbol(f22, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 20, 5)) + + // Regular void function because contextual type for implicit return isn't just undefined +} + +async function f30(): Promise { +>f30 : Symbol(f30, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 22, 1)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + + // Ok, return type allows implicit return of undefined +} + +async function f31(): Promise { +>f31 : Symbol(f31, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 26, 1)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) - // Okay; return type allows implicit return of undefined + // Error, return type isn't just undefined } -async function f4(): Promise { ->f4 : Symbol(f4, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 10, 1)) +async function f32(): Promise { +>f32 : Symbol(f32, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 30, 1)) >Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) - // Error; return type does not include undefined + // Error, return type doesn't include undefined +} + +// Examples from #36288 + +declare function f(a: () => undefined): void; +>f : Symbol(f, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 34, 1)) +>a : Symbol(a, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 38, 19)) + +f(() => { }); +>f : Symbol(f, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 34, 1)) + +f((): undefined => { }); +>f : Symbol(f, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 34, 1)) + +const g1: () => undefined = () => { }; +>g1 : Symbol(g1, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 44, 5)) + +const g2 = (): undefined => { }; +>g2 : Symbol(g2, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 46, 5)) + +function h1() { +>h1 : Symbol(h1, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 46, 32)) } +f(h1); // Error +>f : Symbol(f, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 34, 1)) +>h1 : Symbol(h1, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 46, 32)) + +function h2(): undefined { +>h2 : Symbol(h2, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 51, 6)) +} + +f(h2); +>f : Symbol(f, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 34, 1)) +>h2 : Symbol(h2, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 51, 6)) + diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types index beb7ae82be089..f09f272071721 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types @@ -1,25 +1,100 @@ === tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts === -function f1(): undefined | number { ->f1 : () => undefined | number +function f10(): undefined { +>f10 : () => undefined - // Okay; return type allows implicit return of undefined + // Ok, return type allows implicit return of undefined } -function f2(): number { ->f2 : () => number +function f11(): undefined | number { +>f11 : () => undefined | number - // Error; return type does not include undefined + // Error, return type isn't just undefined } -async function f3(): Promise { ->f3 : () => Promise +function f12(): number { +>f12 : () => number - // Okay; return type allows implicit return of undefined + // Error, return type doesn't include undefined } -async function f4(): Promise { ->f4 : () => Promise +const f20: () => undefined = () => { +>f20 : () => undefined +>() => { // Ok, contextual type for implicit return is undefined} : () => undefined - // Error; return type does not include undefined + // Ok, contextual type for implicit return is undefined } +const f21: () => undefined | number = () => { +>f21 : () => undefined | number +>() => { // Regular void function because contextual type for implicit return isn't just undefined} : () => void + + // Regular void function because contextual type for implicit return isn't just undefined +} + +const f22: () => number = () => { +>f22 : () => number +>() => { // Regular void function because contextual type for implicit return isn't just undefined} : () => void + + // Regular void function because contextual type for implicit return isn't just undefined +} + +async function f30(): Promise { +>f30 : () => Promise + + // Ok, return type allows implicit return of undefined +} + +async function f31(): Promise { +>f31 : () => Promise + + // Error, return type isn't just undefined +} + +async function f32(): Promise { +>f32 : () => Promise + + // Error, return type doesn't include undefined +} + +// Examples from #36288 + +declare function f(a: () => undefined): void; +>f : (a: () => undefined) => void +>a : () => undefined + +f(() => { }); +>f(() => { }) : void +>f : (a: () => undefined) => void +>() => { } : () => undefined + +f((): undefined => { }); +>f((): undefined => { }) : void +>f : (a: () => undefined) => void +>(): undefined => { } : () => undefined + +const g1: () => undefined = () => { }; +>g1 : () => undefined +>() => { } : () => undefined + +const g2 = (): undefined => { }; +>g2 : () => undefined +>(): undefined => { } : () => undefined + +function h1() { +>h1 : () => void +} + +f(h1); // Error +>f(h1) : void +>f : (a: () => undefined) => void +>h1 : () => void + +function h2(): undefined { +>h2 : () => undefined +} + +f(h2); +>f(h2) : void +>f : (a: () => undefined) => void +>h2 : () => undefined + diff --git a/tests/baselines/reference/unknownType1.errors.txt b/tests/baselines/reference/unknownType1.errors.txt index f86564eb5ce8b..82338d24ffcd8 100644 --- a/tests/baselines/reference/unknownType1.errors.txt +++ b/tests/baselines/reference/unknownType1.errors.txt @@ -20,6 +20,7 @@ tests/cases/conformance/types/unknown/unknownType1.ts(128,5): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(129,5): error TS2322: Type 'number' is not assignable to type '{ [x: string]: unknown; }'. tests/cases/conformance/types/unknown/unknownType1.ts(143,29): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(144,29): error TS2698: Spread types may only be created from object types. +tests/cases/conformance/types/unknown/unknownType1.ts(150,17): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/types/unknown/unknownType1.ts(156,14): error TS2700: Rest types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(162,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. tests/cases/conformance/types/unknown/unknownType1.ts(170,9): error TS2322: Type 'T' is not assignable to type '{}'. @@ -27,7 +28,7 @@ tests/cases/conformance/types/unknown/unknownType1.ts(171,9): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type 'T' is not assignable to type '{}'. -==== tests/cases/conformance/types/unknown/unknownType1.ts (26 errors) ==== +==== tests/cases/conformance/types/unknown/unknownType1.ts (27 errors) ==== // In an intersection everything absorbs unknown type T00 = unknown & null; // null @@ -221,6 +222,8 @@ tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type // Functions with unknown return type don't need return expressions function f27(): unknown { + ~~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } // Rest type cannot be created from unknown From 37b10482cca073a511c91fcc7f8616b7eac84a8d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 1 Apr 2023 08:48:14 -0700 Subject: [PATCH 7/9] Align rules for --noImplicitReturns in functions with no return annotations --- src/compiler/checker.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48ec31a394db1..2c80e761cbb70 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35700,7 +35700,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } const inferredReturnType = getReturnTypeOfSignature(getSignatureFromDeclaration(func)); - if (isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(func, inferredReturnType)) { + if (isUnwrappedReturnTypeUndefinedVoidOrAny(func, inferredReturnType)) { return; } } @@ -42184,9 +42184,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isAsync ? getAwaitedTypeNoAlias(returnType) || errorType : returnType; } - function isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(func: SignatureDeclaration, returnType: Type): boolean { - const unwrappedReturnType = unwrapReturnType(returnType, getFunctionFlags(func)); - return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.AnyOrUnknown); + function isUnwrappedReturnTypeUndefinedVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean { + const type = unwrapReturnType(returnType, getFunctionFlags(func)); + return !!(type && (maybeTypeOfKind(type, TypeFlags.Void) || type.flags & (TypeFlags.Any | TypeFlags.Undefined))); } function checkReturnStatement(node: ReturnStatement) { @@ -42234,7 +42234,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeUndefinedVoidAnyOrUnknown(container, returnType)) { + else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeUndefinedVoidOrAny(container, returnType)) { // The function has a return type, but the return statement doesn't have an expression. error(node, Diagnostics.Not_all_code_paths_return_a_value); } From 7d54015c55e0ce425f770bb6a047c2379effff65 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 1 Apr 2023 08:48:31 -0700 Subject: [PATCH 8/9] Add more tests --- .../noImplicitReturnsExclusions.errors.txt | 78 +++++++++++ .../noImplicitReturnsExclusions.symbols | 124 +++++++++++++++++ .../noImplicitReturnsExclusions.types | 129 ++++++++++++++++++ .../compiler/noImplicitReturnsExclusions.ts | 60 ++++++++ 4 files changed, 391 insertions(+) create mode 100644 tests/baselines/reference/noImplicitReturnsExclusions.errors.txt create mode 100644 tests/baselines/reference/noImplicitReturnsExclusions.symbols create mode 100644 tests/baselines/reference/noImplicitReturnsExclusions.types create mode 100644 tests/cases/compiler/noImplicitReturnsExclusions.ts diff --git a/tests/baselines/reference/noImplicitReturnsExclusions.errors.txt b/tests/baselines/reference/noImplicitReturnsExclusions.errors.txt new file mode 100644 index 0000000000000..74a54748f2c20 --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnsExclusions.errors.txt @@ -0,0 +1,78 @@ +tests/cases/compiler/noImplicitReturnsExclusions.ts(16,26): error TS7030: Not all code paths return a value. +tests/cases/compiler/noImplicitReturnsExclusions.ts(24,26): error TS7030: Not all code paths return a value. +tests/cases/compiler/noImplicitReturnsExclusions.ts(40,10): error TS7030: Not all code paths return a value. +tests/cases/compiler/noImplicitReturnsExclusions.ts(44,10): error TS7030: Not all code paths return a value. +tests/cases/compiler/noImplicitReturnsExclusions.ts(48,10): error TS7030: Not all code paths return a value. +tests/cases/compiler/noImplicitReturnsExclusions.ts(53,10): error TS7030: Not all code paths return a value. + + +==== tests/cases/compiler/noImplicitReturnsExclusions.ts (6 errors) ==== + // Functions with a return type of any, undefined, or a type that includes void are excluded + // from --noImplicitReturns checks. + + function f1(b: boolean): undefined { + if (b) return undefined; + } + + function f2(b: boolean): void { + if (b) return undefined; + } + + function f3(b: boolean): any { + if (b) return undefined; + } + + function f4(b: boolean): string | undefined { // Error + ~~~~~~~~~~~~~~~~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return undefined; + } + + function f5(b: boolean): string | void { + if (b) return undefined; + } + + function f6(b: boolean): unknown { // Error + ~~~~~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return undefined; + } + + function f10(b: boolean) { + if (b) return; + } + + function f11(b: boolean) { + if (b) return undefined; + } + + function f12(b: boolean) { + if (b) return undefined as any; + } + + function f13(b: boolean) { // Error + ~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return undefined as unknown; + } + + function f14(b: boolean) { // Error + ~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return 42; + } + + function f15(b: boolean) { // Error + ~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return 42; + if (b) return undefined; + } + + function f16(b: boolean) { // Error + ~~~ +!!! error TS7030: Not all code paths return a value. + if (b) return 42; + if (b) return; + } + \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitReturnsExclusions.symbols b/tests/baselines/reference/noImplicitReturnsExclusions.symbols new file mode 100644 index 0000000000000..56a3eea64f5cb --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnsExclusions.symbols @@ -0,0 +1,124 @@ +=== tests/cases/compiler/noImplicitReturnsExclusions.ts === +// Functions with a return type of any, undefined, or a type that includes void are excluded +// from --noImplicitReturns checks. + +function f1(b: boolean): undefined { +>f1 : Symbol(f1, Decl(noImplicitReturnsExclusions.ts, 0, 0)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 3, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 3, 12)) +>undefined : Symbol(undefined) +} + +function f2(b: boolean): void { +>f2 : Symbol(f2, Decl(noImplicitReturnsExclusions.ts, 5, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 7, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 7, 12)) +>undefined : Symbol(undefined) +} + +function f3(b: boolean): any { +>f3 : Symbol(f3, Decl(noImplicitReturnsExclusions.ts, 9, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 11, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 11, 12)) +>undefined : Symbol(undefined) +} + +function f4(b: boolean): string | undefined { // Error +>f4 : Symbol(f4, Decl(noImplicitReturnsExclusions.ts, 13, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 15, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 15, 12)) +>undefined : Symbol(undefined) +} + +function f5(b: boolean): string | void { +>f5 : Symbol(f5, Decl(noImplicitReturnsExclusions.ts, 17, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 19, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 19, 12)) +>undefined : Symbol(undefined) +} + +function f6(b: boolean): unknown { // Error +>f6 : Symbol(f6, Decl(noImplicitReturnsExclusions.ts, 21, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 23, 12)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 23, 12)) +>undefined : Symbol(undefined) +} + +function f10(b: boolean) { +>f10 : Symbol(f10, Decl(noImplicitReturnsExclusions.ts, 25, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 27, 13)) + + if (b) return; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 27, 13)) +} + +function f11(b: boolean) { +>f11 : Symbol(f11, Decl(noImplicitReturnsExclusions.ts, 29, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 31, 13)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 31, 13)) +>undefined : Symbol(undefined) +} + +function f12(b: boolean) { +>f12 : Symbol(f12, Decl(noImplicitReturnsExclusions.ts, 33, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 35, 13)) + + if (b) return undefined as any; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 35, 13)) +>undefined : Symbol(undefined) +} + +function f13(b: boolean) { // Error +>f13 : Symbol(f13, Decl(noImplicitReturnsExclusions.ts, 37, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 39, 13)) + + if (b) return undefined as unknown; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 39, 13)) +>undefined : Symbol(undefined) +} + +function f14(b: boolean) { // Error +>f14 : Symbol(f14, Decl(noImplicitReturnsExclusions.ts, 41, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 43, 13)) + + if (b) return 42; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 43, 13)) +} + +function f15(b: boolean) { // Error +>f15 : Symbol(f15, Decl(noImplicitReturnsExclusions.ts, 45, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 47, 13)) + + if (b) return 42; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 47, 13)) + + if (b) return undefined; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 47, 13)) +>undefined : Symbol(undefined) +} + +function f16(b: boolean) { // Error +>f16 : Symbol(f16, Decl(noImplicitReturnsExclusions.ts, 50, 1)) +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 52, 13)) + + if (b) return 42; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 52, 13)) + + if (b) return; +>b : Symbol(b, Decl(noImplicitReturnsExclusions.ts, 52, 13)) +} + diff --git a/tests/baselines/reference/noImplicitReturnsExclusions.types b/tests/baselines/reference/noImplicitReturnsExclusions.types new file mode 100644 index 0000000000000..a0c44c8afbb6e --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnsExclusions.types @@ -0,0 +1,129 @@ +=== tests/cases/compiler/noImplicitReturnsExclusions.ts === +// Functions with a return type of any, undefined, or a type that includes void are excluded +// from --noImplicitReturns checks. + +function f1(b: boolean): undefined { +>f1 : (b: boolean) => undefined +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f2(b: boolean): void { +>f2 : (b: boolean) => void +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f3(b: boolean): any { +>f3 : (b: boolean) => any +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f4(b: boolean): string | undefined { // Error +>f4 : (b: boolean) => string | undefined +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f5(b: boolean): string | void { +>f5 : (b: boolean) => string | void +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f6(b: boolean): unknown { // Error +>f6 : (b: boolean) => unknown +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f10(b: boolean) { +>f10 : (b: boolean) => void +>b : boolean + + if (b) return; +>b : boolean +} + +function f11(b: boolean) { +>f11 : (b: boolean) => undefined +>b : boolean + + if (b) return undefined; +>b : boolean +>undefined : undefined +} + +function f12(b: boolean) { +>f12 : (b: boolean) => any +>b : boolean + + if (b) return undefined as any; +>b : boolean +>undefined as any : any +>undefined : undefined +} + +function f13(b: boolean) { // Error +>f13 : (b: boolean) => unknown +>b : boolean + + if (b) return undefined as unknown; +>b : boolean +>undefined as unknown : unknown +>undefined : undefined +} + +function f14(b: boolean) { // Error +>f14 : (b: boolean) => 42 | undefined +>b : boolean + + if (b) return 42; +>b : boolean +>42 : 42 +} + +function f15(b: boolean) { // Error +>f15 : (b: boolean) => 42 | undefined +>b : boolean + + if (b) return 42; +>b : boolean +>42 : 42 + + if (b) return undefined; +>b : false +>undefined : undefined +} + +function f16(b: boolean) { // Error +>f16 : (b: boolean) => 42 | undefined +>b : boolean + + if (b) return 42; +>b : boolean +>42 : 42 + + if (b) return; +>b : false +} + diff --git a/tests/cases/compiler/noImplicitReturnsExclusions.ts b/tests/cases/compiler/noImplicitReturnsExclusions.ts new file mode 100644 index 0000000000000..61226026e5c94 --- /dev/null +++ b/tests/cases/compiler/noImplicitReturnsExclusions.ts @@ -0,0 +1,60 @@ +// @strict: true +// @noImplicitReturns: true +// @noEmit: true + +// Functions with a return type of any, undefined, or a type that includes void are excluded +// from --noImplicitReturns checks. + +function f1(b: boolean): undefined { + if (b) return undefined; +} + +function f2(b: boolean): void { + if (b) return undefined; +} + +function f3(b: boolean): any { + if (b) return undefined; +} + +function f4(b: boolean): string | undefined { // Error + if (b) return undefined; +} + +function f5(b: boolean): string | void { + if (b) return undefined; +} + +function f6(b: boolean): unknown { // Error + if (b) return undefined; +} + +function f10(b: boolean) { + if (b) return; +} + +function f11(b: boolean) { + if (b) return undefined; +} + +function f12(b: boolean) { + if (b) return undefined as any; +} + +function f13(b: boolean) { // Error + if (b) return undefined as unknown; +} + +function f14(b: boolean) { // Error + if (b) return 42; +} + +function f15(b: boolean) { // Error + if (b) return 42; + if (b) return undefined; +} + +function f16(b: boolean) { // Error + if (b) return 42; + if (b) return; +} From 40f951202e2dbdbccdbefe6aa6b465a70ab4bc19 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 1 Apr 2023 08:51:09 -0700 Subject: [PATCH 9/9] Address CR feedback --- ...urnStatementsAndExpressionsStrictNullChecks.errors.txt | 4 ++-- ...ssingReturnStatementsAndExpressionsStrictNullChecks.js | 8 ++++---- ...ReturnStatementsAndExpressionsStrictNullChecks.symbols | 4 ++-- ...ngReturnStatementsAndExpressionsStrictNullChecks.types | 8 ++++---- ...ssingReturnStatementsAndExpressionsStrictNullChecks.ts | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt index dccad1eccf8e6..6e9b3c4743f6e 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.errors.txt @@ -35,14 +35,14 @@ tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChe ~~~ !!! error TS2322: Type '() => void' is not assignable to type '() => number | undefined'. !!! error TS2322: Type 'void' is not assignable to type 'number | undefined'. - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } const f22: () => number = () => { ~~~ !!! error TS2322: Type '() => void' is not assignable to type '() => number'. !!! error TS2322: Type 'void' is not assignable to type 'number'. - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } async function f30(): Promise { diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js index 99801b800481d..5f39a68dc03b9 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.js @@ -16,11 +16,11 @@ const f20: () => undefined = () => { } const f21: () => undefined | number = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } const f22: () => number = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } async function f30(): Promise { @@ -72,10 +72,10 @@ const f20 = () => { // Ok, contextual type for implicit return is undefined }; const f21 = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined }; const f22 = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined }; async function f30() { // Ok, return type allows implicit return of undefined diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols index 121cf61a005fb..edde1a20df55e 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.symbols @@ -26,13 +26,13 @@ const f20: () => undefined = () => { const f21: () => undefined | number = () => { >f21 : Symbol(f21, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 16, 5)) - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } const f22: () => number = () => { >f22 : Symbol(f22, Decl(functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts, 20, 5)) - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } async function f30(): Promise { diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types index f09f272071721..8f149662584d0 100644 --- a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.types @@ -26,16 +26,16 @@ const f20: () => undefined = () => { const f21: () => undefined | number = () => { >f21 : () => undefined | number ->() => { // Regular void function because contextual type for implicit return isn't just undefined} : () => void +>() => { // Error, regular void function because contextual type for implicit return isn't just undefined} : () => void - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } const f22: () => number = () => { >f22 : () => number ->() => { // Regular void function because contextual type for implicit return isn't just undefined} : () => void +>() => { // Error, regular void function because contextual type for implicit return isn't just undefined} : () => void - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } async function f30(): Promise { diff --git a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts index a43266bb2b75b..be6828cd35725 100644 --- a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts +++ b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressionsStrictNullChecks.ts @@ -19,11 +19,11 @@ const f20: () => undefined = () => { } const f21: () => undefined | number = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } const f22: () => number = () => { - // Regular void function because contextual type for implicit return isn't just undefined + // Error, regular void function because contextual type for implicit return isn't just undefined } async function f30(): Promise {