Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35469,8 +35469,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const functionFlags = getFunctionFlags(func);
const type = returnType && unwrapReturnType(returnType, functionFlags);

// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) {
// Functions with an explicitly specified 'undefined, 'void' or 'any' return type don't need any return expressions.
if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any)) {
return;
}

Expand All @@ -35489,9 +35489,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.
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_void_nor_any_must_return_a_value_undefined_is_also_allowed_with_strictNullChecks);
}
else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) {
else if (type && strictNullChecks) {
error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
}
else if (compilerOptions.noImplicitReturns) {
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1868,7 +1868,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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.": {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather us duplicate this message to have two (Daniel Rosenwasser (@DanielRosenwasser) may be able to better write these):

A function whose declared type is neither 'void' nor 'any' must return a value.

A function whose declared type is not 'void', 'any', or 'undefined' must return a value.

Then, conditionally emit one based on the variable strictNullChecks.

Then below in codefixes/returnValueCorrect.ts, handle both.

"category": "Error",
"code": 2355
},
Expand Down Expand Up @@ -6706,7 +6706,7 @@
"category": "Suggestion",
"code": 80010
},

"Add missing 'super()' call": {
"category": "Message",
"code": 90001
Expand Down
4 changes: 2 additions & 2 deletions src/services/codefixes/returnValueCorrect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ 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_void_nor_any_must_return_a_value_undefined_is_also_allowed_with_strictNullChecks.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
];
Expand Down Expand Up @@ -213,7 +213,7 @@ 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_void_nor_any_must_return_a_value_undefined_is_also_allowed_with_strictNullChecks.code:
if (!declaration || !declaration.body || !declaration.type || !rangeContainsRange(declaration.type, node)) return undefined;
return getFixInfo(checker, declaration, checker.getTypeFromTypeNode(declaration.type), /* isFunctionType */ false);
case Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code:
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/ParameterList5.errors.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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'.


==== 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
~~~~~~~~
!!! error TS2369: A parameter property is only allowed in a constructor implementation.
~
Expand Down
Original file line number Diff line number Diff line change
@@ -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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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<T>' are incompatible.
Expand All @@ -22,15 +22,15 @@ 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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.
async function fn4(): number { } // error
~~~~~~
!!! 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
async function fn5(): PromiseLike<void> { } // 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T> 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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<T> type. Did you mean to write 'Promise<any>'?
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<T> type. Did you mean to write 'Promise<number>'?
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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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<T> type. Did you mean to write 'Promise<void>'?
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<T> type. Did you mean to write 'Promise<void>'?
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.
Expand All @@ -19,15 +19,15 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
~~~
!!! error TS1064: The return type of an async function or method must be the global Promise<T> 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
async function fn3(): any { } // error
~~~
!!! error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<any>'?
async function fn4(): number { } // error
~~~~~~
!!! error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
async function fn5(): PromiseLike<void> { } // error
~~~~~~~~~~~~~~~~~
!!! error TS1064: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<void>'?
Expand Down
Original file line number Diff line number Diff line change
@@ -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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.


==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (7 errors) ====
Expand All @@ -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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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.
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
4 changes: 2 additions & 2 deletions tests/baselines/reference/controlFlowGenericTypes.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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<unknown>'.
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 TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(90,44): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
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'.
Expand Down Expand Up @@ -109,7 +109,7 @@ tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(168,9): error TS1

const fn2 = <T extends MyUnion>(value: T): MyUnion => {
~~~~~~~
!!! 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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.
value.foo; // Error
~~~
!!! error TS2339: Property 'foo' does not exist on type 'MyUnion'.
Expand Down
Original file line number Diff line number Diff line change
@@ -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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.


==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (2 errors) ====
Expand All @@ -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 'void' nor 'any' must return a value. 'undefined' is also allowed with --strictNullChecks.

Loading