Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3cf26e4

Browse filesBrowse files
authored
fix(43160): improve error location for functions without explicit return (microsoft#43367)
* fix(43160): improve error location for functions without explicit return * handle functions returning never
1 parent 3b06ef1 commit 3cf26e4
Copy full SHA for 3cf26e4

5 files changed

+303-5Lines changed: 303 additions & 5 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30574,18 +30574,18 @@ namespace ts {
3057430574
}
3057530575

3057630576
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
30577+
const errorNode = getEffectiveReturnTypeNode(func) || func;
3057730578

3057830579
if (type && type.flags & TypeFlags.Never) {
30579-
error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
30580+
error(errorNode, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
3058030581
}
3058130582
else if (type && !hasExplicitReturn) {
3058230583
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
3058330584
// this function does not conform to the specification.
30584-
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
30585-
error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
30585+
error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
3058630586
}
3058730587
else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) {
30588-
error(getEffectiveReturnTypeNode(func) || func, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
30588+
error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
3058930589
}
3059030590
else if (compilerOptions.noImplicitReturns) {
3059130591
if (!type) {
@@ -30600,7 +30600,7 @@ namespace ts {
3060030600
return;
3060130601
}
3060230602
}
30603-
error(getEffectiveReturnTypeNode(func) || func, Diagnostics.Not_all_code_paths_return_a_value);
30603+
error(errorNode, Diagnostics.Not_all_code_paths_return_a_value);
3060430604
}
3060530605
}
3060630606

Collapse file
+74Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
tests/cases/conformance/jsdoc/foo.js(7,10): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
2+
tests/cases/conformance/jsdoc/foo.js(13,5): error TS2322: Type 'string' is not assignable to type 'number'.
3+
tests/cases/conformance/jsdoc/foo.js(16,60): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
4+
tests/cases/conformance/jsdoc/foo.js(21,20): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
5+
tests/cases/conformance/jsdoc/foo.js(31,10): error TS2534: A function returning 'never' cannot have a reachable end point.
6+
tests/cases/conformance/jsdoc/foo.js(37,5): error TS2322: Type 'string' is not assignable to type 'never'.
7+
tests/cases/conformance/jsdoc/foo.js(40,56): error TS2534: A function returning 'never' cannot have a reachable end point.
8+
tests/cases/conformance/jsdoc/foo.js(45,18): error TS2534: A function returning 'never' cannot have a reachable end point.
9+
10+
11+
==== tests/cases/conformance/jsdoc/foo.js (8 errors) ====
12+
/**
13+
* @callback FunctionReturningPromise
14+
* @returns {Promise<number>}
15+
*/
16+
17+
/** @type {FunctionReturningPromise} */
18+
function testPromise1() {
19+
~~~~~~~~~~~~
20+
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
21+
console.log("Nope");
22+
}
23+
24+
/** @type {FunctionReturningPromise} */
25+
async function testPromise2() {
26+
return "asd";
27+
~~~~~~~~~~~~~
28+
!!! error TS2322: Type 'string' is not assignable to type 'number'.
29+
}
30+
31+
var testPromise3 = /** @type {FunctionReturningPromise} */ function() {
32+
~~~~~~~~
33+
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
34+
console.log("test")
35+
}
36+
37+
/** @type {FunctionReturningPromise} */
38+
var testPromise4 = function() {
39+
~~~~~~~~
40+
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
41+
console.log("test")
42+
}
43+
44+
/**
45+
* @callback FunctionReturningNever
46+
* @returns {never}
47+
*/
48+
49+
/** @type {FunctionReturningNever} */
50+
function testNever1() {
51+
~~~~~~~~~~
52+
!!! error TS2534: A function returning 'never' cannot have a reachable end point.
53+
54+
}
55+
56+
/** @type {FunctionReturningNever} */
57+
async function testNever2() {
58+
return "asd";
59+
~~~~~~~~~~~~~
60+
!!! error TS2322: Type 'string' is not assignable to type 'never'.
61+
}
62+
63+
var testNever3 = /** @type {FunctionReturningNever} */ function() {
64+
~~~~~~~~
65+
!!! error TS2534: A function returning 'never' cannot have a reachable end point.
66+
console.log("test")
67+
}
68+
69+
/** @type {FunctionReturningNever} */
70+
var testNever4 = function() {
71+
~~~~~~~~
72+
!!! error TS2534: A function returning 'never' cannot have a reachable end point.
73+
console.log("test")
74+
}
Collapse file
+78Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
=== tests/cases/conformance/jsdoc/foo.js ===
2+
/**
3+
* @callback FunctionReturningPromise
4+
* @returns {Promise<number>}
5+
*/
6+
7+
/** @type {FunctionReturningPromise} */
8+
function testPromise1() {
9+
>testPromise1 : Symbol(testPromise1, Decl(foo.js, 0, 0))
10+
11+
console.log("Nope");
12+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
13+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
14+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
15+
}
16+
17+
/** @type {FunctionReturningPromise} */
18+
async function testPromise2() {
19+
>testPromise2 : Symbol(testPromise2, Decl(foo.js, 8, 1))
20+
21+
return "asd";
22+
}
23+
24+
var testPromise3 = /** @type {FunctionReturningPromise} */ function() {
25+
>testPromise3 : Symbol(testPromise3, Decl(foo.js, 15, 3))
26+
27+
console.log("test")
28+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
29+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
30+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
31+
}
32+
33+
/** @type {FunctionReturningPromise} */
34+
var testPromise4 = function() {
35+
>testPromise4 : Symbol(testPromise4, Decl(foo.js, 20, 3))
36+
37+
console.log("test")
38+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
39+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
40+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
41+
}
42+
43+
/**
44+
* @callback FunctionReturningNever
45+
* @returns {never}
46+
*/
47+
48+
/** @type {FunctionReturningNever} */
49+
function testNever1() {
50+
>testNever1 : Symbol(testNever1, Decl(foo.js, 22, 1))
51+
52+
}
53+
54+
/** @type {FunctionReturningNever} */
55+
async function testNever2() {
56+
>testNever2 : Symbol(testNever2, Decl(foo.js, 32, 1))
57+
58+
return "asd";
59+
}
60+
61+
var testNever3 = /** @type {FunctionReturningNever} */ function() {
62+
>testNever3 : Symbol(testNever3, Decl(foo.js, 39, 3))
63+
64+
console.log("test")
65+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
66+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
67+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
68+
}
69+
70+
/** @type {FunctionReturningNever} */
71+
var testNever4 = function() {
72+
>testNever4 : Symbol(testNever4, Decl(foo.js, 44, 3))
73+
74+
console.log("test")
75+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
76+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
77+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
78+
}
Collapse file
+94Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
=== tests/cases/conformance/jsdoc/foo.js ===
2+
/**
3+
* @callback FunctionReturningPromise
4+
* @returns {Promise<number>}
5+
*/
6+
7+
/** @type {FunctionReturningPromise} */
8+
function testPromise1() {
9+
>testPromise1 : () => Promise<number>
10+
11+
console.log("Nope");
12+
>console.log("Nope") : void
13+
>console.log : (...data: any[]) => void
14+
>console : Console
15+
>log : (...data: any[]) => void
16+
>"Nope" : "Nope"
17+
}
18+
19+
/** @type {FunctionReturningPromise} */
20+
async function testPromise2() {
21+
>testPromise2 : () => Promise<number>
22+
23+
return "asd";
24+
>"asd" : "asd"
25+
}
26+
27+
var testPromise3 = /** @type {FunctionReturningPromise} */ function() {
28+
>testPromise3 : FunctionReturningPromise
29+
>function() { console.log("test")} : () => Promise<number>
30+
31+
console.log("test")
32+
>console.log("test") : void
33+
>console.log : (...data: any[]) => void
34+
>console : Console
35+
>log : (...data: any[]) => void
36+
>"test" : "test"
37+
}
38+
39+
/** @type {FunctionReturningPromise} */
40+
var testPromise4 = function() {
41+
>testPromise4 : FunctionReturningPromise
42+
>function() { console.log("test")} : () => Promise<number>
43+
44+
console.log("test")
45+
>console.log("test") : void
46+
>console.log : (...data: any[]) => void
47+
>console : Console
48+
>log : (...data: any[]) => void
49+
>"test" : "test"
50+
}
51+
52+
/**
53+
* @callback FunctionReturningNever
54+
* @returns {never}
55+
*/
56+
57+
/** @type {FunctionReturningNever} */
58+
function testNever1() {
59+
>testNever1 : () => never
60+
61+
}
62+
63+
/** @type {FunctionReturningNever} */
64+
async function testNever2() {
65+
>testNever2 : () => never
66+
67+
return "asd";
68+
>"asd" : "asd"
69+
}
70+
71+
var testNever3 = /** @type {FunctionReturningNever} */ function() {
72+
>testNever3 : FunctionReturningNever
73+
>function() { console.log("test")} : () => never
74+
75+
console.log("test")
76+
>console.log("test") : void
77+
>console.log : (...data: any[]) => void
78+
>console : Console
79+
>log : (...data: any[]) => void
80+
>"test" : "test"
81+
}
82+
83+
/** @type {FunctionReturningNever} */
84+
var testNever4 = function() {
85+
>testNever4 : FunctionReturningNever
86+
>function() { console.log("test")} : () => never
87+
88+
console.log("test")
89+
>console.log("test") : void
90+
>console.log : (...data: any[]) => void
91+
>console : Console
92+
>log : (...data: any[]) => void
93+
>"test" : "test"
94+
}
Collapse file
+52Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// @noEmit: true
2+
// @allowJs: true
3+
// @checkJs: true
4+
// @Filename: foo.js
5+
6+
/**
7+
* @callback FunctionReturningPromise
8+
* @returns {Promise<number>}
9+
*/
10+
11+
/** @type {FunctionReturningPromise} */
12+
function testPromise1() {
13+
console.log("Nope");
14+
}
15+
16+
/** @type {FunctionReturningPromise} */
17+
async function testPromise2() {
18+
return "asd";
19+
}
20+
21+
var testPromise3 = /** @type {FunctionReturningPromise} */ function() {
22+
console.log("test")
23+
}
24+
25+
/** @type {FunctionReturningPromise} */
26+
var testPromise4 = function() {
27+
console.log("test")
28+
}
29+
30+
/**
31+
* @callback FunctionReturningNever
32+
* @returns {never}
33+
*/
34+
35+
/** @type {FunctionReturningNever} */
36+
function testNever1() {
37+
38+
}
39+
40+
/** @type {FunctionReturningNever} */
41+
async function testNever2() {
42+
return "asd";
43+
}
44+
45+
var testNever3 = /** @type {FunctionReturningNever} */ function() {
46+
console.log("test")
47+
}
48+
49+
/** @type {FunctionReturningNever} */
50+
var testNever4 = function() {
51+
console.log("test")
52+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.