diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 169a922b7d08e..37db043f38c9c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7566,12 +7566,21 @@ namespace ts { const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); return getAnnotatedAccessorType(setter); } - + const typeFromTag = getReturnTypeOfTypeTag(declaration); + if (typeFromTag) { + return typeFromTag; + } if (nodeIsMissing((declaration).body)) { return anyType; } } + function getReturnTypeOfTypeTag(node: SignatureDeclaration | JSDocSignature) { + const typeTag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined; + const signatures = typeTag && typeTag.typeExpression && getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call); + return signatures && signatures.length === 1 ? getReturnTypeOfSignature(signatures[0]) : undefined; + } + function containsArgumentsReference(declaration: SignatureDeclaration): boolean { const links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { @@ -20521,15 +20530,20 @@ namespace ts { return type; } + function getReturnOrPromisedType(node: FunctionLikeDeclaration | MethodSignature, functionFlags: FunctionFlags) { + const returnTypeNode = getEffectiveReturnTypeNode(node); + return returnTypeNode && + ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ? + checkAsyncFunctionReturnType(node, returnTypeNode) : // Async function + getTypeFromTypeNode(returnTypeNode)) || // AsyncGenerator function, Generator function, or normal function + getReturnTypeOfTypeTag(node); // type from JSDoc @type tag + } + function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const functionFlags = getFunctionFlags(node); - const returnTypeNode = getEffectiveReturnTypeNode(node); - const returnOrPromisedType = returnTypeNode && - ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ? - checkAsyncFunctionReturnType(node) : // Async function - getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function + const returnOrPromisedType = getReturnOrPromisedType(node, functionFlags); if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function // return is not necessary in the body of generators @@ -20537,7 +20551,7 @@ namespace ts { } if (node.body) { - if (!returnTypeNode) { + if (!getEffectiveReturnTypeNode(node)) { // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors // we need. An example is the noImplicitAny errors resulting from widening the return expression // of a function. Because checking of function expression bodies is deferred, there was never an @@ -21989,7 +22003,7 @@ namespace ts { } } else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { - checkAsyncFunctionReturnType(node); + checkAsyncFunctionReturnType(node, returnTypeNode); } } if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) { @@ -23049,7 +23063,7 @@ namespace ts { * * @param node The signature to check */ - function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature): Type { + function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature, returnTypeNode: TypeNode): Type { // As part of our emit for an async function, we will need to emit the entity name of // the return type annotation as an expression. To meet the necessary runtime semantics // for __awaiter, we must also check that the type of the declaration (e.g. the static @@ -23074,7 +23088,6 @@ namespace ts { // then(...): Promise; // } // - const returnTypeNode = getEffectiveReturnTypeNode(node)!; // TODO: GH#18217 const returnType = getTypeFromTypeNode(returnTypeNode); if (languageVersion >= ScriptTarget.ES2015) { @@ -23484,15 +23497,12 @@ namespace ts { const body = node.kind === SyntaxKind.MethodSignature ? undefined : node.body; checkSourceElement(body); - const returnTypeNode = getEffectiveReturnTypeNode(node); if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function - const returnOrPromisedType = returnTypeNode && (functionFlags & FunctionFlags.Async - ? checkAsyncFunctionReturnType(node) // Async function - : getTypeFromTypeNode(returnTypeNode)); // normal function + const returnOrPromisedType = getReturnOrPromisedType(node, functionFlags); checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } - if (produceDiagnostics && !returnTypeNode) { + if (produceDiagnostics && !getEffectiveReturnTypeNode(node)) { // Report an implicit any error if there is no body, no explicit return type, and node is not a private method // in an ambient context if (noImplicitAny && nodeIsMissing(body) && !isPrivateWithinAmbient(node)) { @@ -23505,6 +23515,13 @@ namespace ts { // yielded values. The only way to trigger these errors is to try checking its return type. getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } + // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature + if (isInJavaScriptFile(node)) { + const typeTag = getJSDocTypeTag(node); + if (typeTag && typeTag.typeExpression && !getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call).length) { + error(typeTag, Diagnostics.The_type_of_a_function_declaration_must_be_callable); + } + } } } @@ -24767,7 +24784,7 @@ namespace ts { error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } - else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) { + else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func) || getReturnTypeOfTypeTag(func)) { if (functionFlags & FunctionFlags.Async) { // Async function const promisedType = getPromisedTypeOfPromise(returnType); const awaitedType = checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 68eafc6b99814..796aabafa1c8a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4017,6 +4017,10 @@ "category": "Error", "code": 8029 }, + "The type of a function declaration must be callable.": { + "category": "Error", + "code": 8030 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 diff --git a/tests/baselines/reference/callbackTag2.types b/tests/baselines/reference/callbackTag2.types index 953d7d335ad68..94c6997b63c4f 100644 --- a/tests/baselines/reference/callbackTag2.types +++ b/tests/baselines/reference/callbackTag2.types @@ -43,7 +43,7 @@ var outside = n => n + 1; /** @type {Final<{ fantasy }, { heroes }>} */ var noreturn = (barts, tidus, noctis) => "cecil" >noreturn : Final<{ fantasy: any; }, { heroes: any; }> ->(barts, tidus, noctis) => "cecil" : (barts: { fantasy: any; }, tidus: { heroes: any; }, noctis: { heroes: any; } & { fantasy: any; }) => "cecil" +>(barts, tidus, noctis) => "cecil" : (barts: { fantasy: any; }, tidus: { heroes: any; }, noctis: { heroes: any; } & { fantasy: any; }) => "cecil" | "zidane" >barts : { fantasy: any; } >tidus : { heroes: any; } >noctis : { heroes: any; } & { fantasy: any; } diff --git a/tests/baselines/reference/callbackTagNamespace.types b/tests/baselines/reference/callbackTagNamespace.types index 8bca9a56a5c46..11d4fa5f7e682 100644 --- a/tests/baselines/reference/callbackTagNamespace.types +++ b/tests/baselines/reference/callbackTagNamespace.types @@ -11,7 +11,7 @@ var x = 1; /** @type {NS.Nested.Inner} */ function f(space, peace) { ->f : (space: any, peace: any) => string +>f : (space: any, peace: any) => string | number >space : any >peace : any diff --git a/tests/baselines/reference/checkJsdocTypeTag1.types b/tests/baselines/reference/checkJsdocTypeTag1.types index a0c0c53cfeb49..f5ec1c0d33786 100644 --- a/tests/baselines/reference/checkJsdocTypeTag1.types +++ b/tests/baselines/reference/checkJsdocTypeTag1.types @@ -61,7 +61,7 @@ y(1); /** @type {function (number)} */ const x1 = (a) => a + 1; >x1 : (arg0: number) => any ->(a) => a + 1 : (a: number) => number +>(a) => a + 1 : (a: number) => any >a : number >a + 1 : number >a : number diff --git a/tests/baselines/reference/checkJsdocTypeTag2.errors.txt b/tests/baselines/reference/checkJsdocTypeTag2.errors.txt index 3590c10e278e5..1f0feacd67547 100644 --- a/tests/baselines/reference/checkJsdocTypeTag2.errors.txt +++ b/tests/baselines/reference/checkJsdocTypeTag2.errors.txt @@ -3,8 +3,7 @@ tests/cases/conformance/jsdoc/0.js(6,5): error TS2322: Type '"hello"' is not ass tests/cases/conformance/jsdoc/0.js(10,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'. tests/cases/conformance/jsdoc/0.js(17,1): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/jsdoc/0.js(20,21): error TS2339: Property 'concat' does not exist on type 'number'. -tests/cases/conformance/jsdoc/0.js(24,7): error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'. - Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/0.js(24,19): error TS2322: Type 'number' is not assignable to type 'string'. ==== tests/cases/conformance/jsdoc/0.js (6 errors) ==== @@ -42,7 +41,6 @@ tests/cases/conformance/jsdoc/0.js(24,7): error TS2322: Type '(a: number) => num /** @type {function (number): string} */ const x4 = (a) => a + 1; - ~~ -!!! error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'. -!!! error TS2322: Type 'number' is not assignable to type 'string'. + ~~~~~ +!!! error TS2322: Type 'number' is not assignable to type 'string'. x4(0); \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag2.types b/tests/baselines/reference/checkJsdocTypeTag2.types index dfee596ca4e86..3fdd286cde1c7 100644 --- a/tests/baselines/reference/checkJsdocTypeTag2.types +++ b/tests/baselines/reference/checkJsdocTypeTag2.types @@ -13,7 +13,7 @@ var n = "hello"; /** @type {function (number)} */ const x1 = (a) => a + 1; >x1 : (arg0: number) => any ->(a) => a + 1 : (a: number) => number +>(a) => a + 1 : (a: number) => any >a : number >a + 1 : number >a : number @@ -47,7 +47,7 @@ a = x2(0); /** @type {function (number): number} */ const x3 = (a) => a.concat("hi"); >x3 : (arg0: number) => number ->(a) => a.concat("hi") : (a: number) => any +>(a) => a.concat("hi") : (a: number) => number >a : number >a.concat("hi") : any >a.concat : any @@ -63,7 +63,7 @@ x3(0); /** @type {function (number): string} */ const x4 = (a) => a + 1; >x4 : (arg0: number) => string ->(a) => a + 1 : (a: number) => number +>(a) => a + 1 : (a: number) => string >a : number >a + 1 : number >a : number diff --git a/tests/baselines/reference/checkJsdocTypeTag5.errors.txt b/tests/baselines/reference/checkJsdocTypeTag5.errors.txt index 98510f63815be..56f6b261d3f96 100644 --- a/tests/baselines/reference/checkJsdocTypeTag5.errors.txt +++ b/tests/baselines/reference/checkJsdocTypeTag5.errors.txt @@ -4,9 +4,11 @@ tests/cases/conformance/jsdoc/test.js(7,24): error TS2322: Type 'number' is not tests/cases/conformance/jsdoc/test.js(10,17): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/jsdoc/test.js(12,14): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/conformance/jsdoc/test.js(14,24): error TS2322: Type 'number' is not assignable to type 'string'. +tests/cases/conformance/jsdoc/test.js(34,5): error TS2322: Type '1 | 2' is not assignable to type '2 | 3'. + Type '1' is not assignable to type '2 | 3'. -==== tests/cases/conformance/jsdoc/test.js (6 errors) ==== +==== tests/cases/conformance/jsdoc/test.js (7 errors) ==== // all 6 should error on return statement/expression /** @type {(x: number) => string} */ function h(x) { return x } @@ -33,4 +35,27 @@ tests/cases/conformance/jsdoc/test.js(14,24): error TS2322: Type 'number' is not var k = function (x) { return x } ~~~~~~~~ !!! error TS2322: Type 'number' is not assignable to type 'string'. + + + /** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */ + /** @type {Argle} */ + function blargle(s) { + return 0; + } + + /** @type {0 | 1 | 2} - assignment should not error */ + var zeroonetwo = blargle('hi') + + /** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */ + + /** @type {Gioconda} */ + function monaLisa(sb) { + return typeof sb === 'string' ? 1 : 2; + } + + /** @type {2 | 3} - overloads are not supported, so there will be an error */ + var twothree = monaLisa(false); + ~~~~~~~~ +!!! error TS2322: Type '1 | 2' is not assignable to type '2 | 3'. +!!! error TS2322: Type '1' is not assignable to type '2 | 3'. \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag5.symbols b/tests/baselines/reference/checkJsdocTypeTag5.symbols index 839fba179ac1f..b1910e5d72d0d 100644 --- a/tests/baselines/reference/checkJsdocTypeTag5.symbols +++ b/tests/baselines/reference/checkJsdocTypeTag5.symbols @@ -36,3 +36,34 @@ var k = function (x) { return x } >x : Symbol(x, Decl(test.js, 13, 18)) >x : Symbol(x, Decl(test.js, 13, 18)) + +/** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */ +/** @type {Argle} */ +function blargle(s) { +>blargle : Symbol(blargle, Decl(test.js, 13, 33)) +>s : Symbol(s, Decl(test.js, 18, 17)) + + return 0; +} + +/** @type {0 | 1 | 2} - assignment should not error */ +var zeroonetwo = blargle('hi') +>zeroonetwo : Symbol(zeroonetwo, Decl(test.js, 23, 3)) +>blargle : Symbol(blargle, Decl(test.js, 13, 33)) + +/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */ + +/** @type {Gioconda} */ +function monaLisa(sb) { +>monaLisa : Symbol(monaLisa, Decl(test.js, 23, 30)) +>sb : Symbol(sb, Decl(test.js, 28, 18)) + + return typeof sb === 'string' ? 1 : 2; +>sb : Symbol(sb, Decl(test.js, 28, 18)) +} + +/** @type {2 | 3} - overloads are not supported, so there will be an error */ +var twothree = monaLisa(false); +>twothree : Symbol(twothree, Decl(test.js, 33, 3)) +>monaLisa : Symbol(monaLisa, Decl(test.js, 23, 30)) + diff --git a/tests/baselines/reference/checkJsdocTypeTag5.types b/tests/baselines/reference/checkJsdocTypeTag5.types index 1038fe0ff3c74..b16904c700d58 100644 --- a/tests/baselines/reference/checkJsdocTypeTag5.types +++ b/tests/baselines/reference/checkJsdocTypeTag5.types @@ -40,3 +40,45 @@ var k = function (x) { return x } >x : number >x : number + +/** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */ +/** @type {Argle} */ +function blargle(s) { +>blargle : (s: "hi" | "bye") => 0 | 1 | 2 +>s : "hi" | "bye" + + return 0; +>0 : 0 +} + +/** @type {0 | 1 | 2} - assignment should not error */ +var zeroonetwo = blargle('hi') +>zeroonetwo : 0 | 1 | 2 +>blargle('hi') : 0 | 1 | 2 +>blargle : (s: "hi" | "bye") => 0 | 1 | 2 +>'hi' : "hi" + +/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */ + +/** @type {Gioconda} */ +function monaLisa(sb) { +>monaLisa : (sb: any) => 1 | 2 +>sb : any + + return typeof sb === 'string' ? 1 : 2; +>typeof sb === 'string' ? 1 : 2 : 1 | 2 +>typeof sb === 'string' : boolean +>typeof sb : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>sb : any +>'string' : "string" +>1 : 1 +>2 : 2 +} + +/** @type {2 | 3} - overloads are not supported, so there will be an error */ +var twothree = monaLisa(false); +>twothree : 2 | 3 +>monaLisa(false) : 1 | 2 +>monaLisa : (sb: any) => 1 | 2 +>false : false + diff --git a/tests/baselines/reference/checkJsdocTypeTag6.errors.txt b/tests/baselines/reference/checkJsdocTypeTag6.errors.txt new file mode 100644 index 0000000000000..18a297eadaeca --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag6.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/jsdoc/test.js(1,5): error TS8030: The type of a function declaration must be callable. +tests/cases/conformance/jsdoc/test.js(7,5): error TS2322: Type '(prop: any) => void' is not assignable to type '{ prop: string; }'. + Property 'prop' is missing in type '(prop: any) => void'. + + +==== tests/cases/conformance/jsdoc/test.js (2 errors) ==== + /** @type {number} */ + ~~~~~~~~~~~~~~ +!!! error TS8030: The type of a function declaration must be callable. + function f() { + return 1 + } + + /** @type {{ prop: string }} */ + var g = function (prop) { + ~ +!!! error TS2322: Type '(prop: any) => void' is not assignable to type '{ prop: string; }'. +!!! error TS2322: Property 'prop' is missing in type '(prop: any) => void'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/checkJsdocTypeTag6.symbols b/tests/baselines/reference/checkJsdocTypeTag6.symbols new file mode 100644 index 0000000000000..73d0dd0401a9f --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag6.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/jsdoc/test.js === +/** @type {number} */ +function f() { +>f : Symbol(f, Decl(test.js, 0, 0)) + + return 1 +} + +/** @type {{ prop: string }} */ +var g = function (prop) { +>g : Symbol(g, Decl(test.js, 6, 3)) +>prop : Symbol(prop, Decl(test.js, 6, 18)) +} + diff --git a/tests/baselines/reference/checkJsdocTypeTag6.types b/tests/baselines/reference/checkJsdocTypeTag6.types new file mode 100644 index 0000000000000..cb1e0e6cb9fa1 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag6.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/jsdoc/test.js === +/** @type {number} */ +function f() { +>f : () => number + + return 1 +>1 : 1 +} + +/** @type {{ prop: string }} */ +var g = function (prop) { +>g : { prop: string; } +>function (prop) {} : (prop: any) => void +>prop : any +} + diff --git a/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.errors.txt b/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.errors.txt index 48559d79cb189..3d1051fdfd441 100644 --- a/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.errors.txt +++ b/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.errors.txt @@ -1,8 +1,6 @@ tests/cases/conformance/jsdoc/0.js(5,3): error TS2322: Type 'number' is not assignable to type 'string | undefined'. -tests/cases/conformance/jsdoc/0.js(7,3): error TS2322: Type '(n1: number) => string' is not assignable to type '(arg0: number) => number'. - Type 'string' is not assignable to type 'number'. -tests/cases/conformance/jsdoc/0.js(11,3): error TS2322: Type '(n1: number) => string' is not assignable to type '(arg0: number) => number'. - Type 'string' is not assignable to type 'number'. +tests/cases/conformance/jsdoc/0.js(8,7): error TS2322: Type '"42"' is not assignable to type 'number'. +tests/cases/conformance/jsdoc/0.js(11,20): error TS2322: Type '"lol"' is not assignable to type 'number'. tests/cases/conformance/jsdoc/0.js(13,15): error TS2322: Type '"0"' is not assignable to type 'number'. tests/cases/conformance/jsdoc/0.js(15,3): error TS2322: Type 'undefined' is not assignable to type 'string'. tests/cases/conformance/jsdoc/0.js(19,5): error TS2322: Type 'number' is not assignable to type 'string'. @@ -19,16 +17,14 @@ tests/cases/conformance/jsdoc/0.js(22,22): error TS2345: Argument of type '"0"' !!! error TS2322: Type 'number' is not assignable to type 'string | undefined'. /** @type {function(number): number} */ method1(n1) { - ~~~~~~~ -!!! error TS2322: Type '(n1: number) => string' is not assignable to type '(arg0: number) => number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. return "42"; + ~~~~~~~~~~~~ +!!! error TS2322: Type '"42"' is not assignable to type 'number'. }, /** @type {function(number): number} */ method2: (n1) => "lol", - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '(n1: number) => string' is not assignable to type '(arg0: number) => number'. -!!! error TS2322: Type 'string' is not assignable to type 'number'. + ~~~~~ +!!! error TS2322: Type '"lol"' is not assignable to type 'number'. /** @type {function(number): number} */ arrowFunc: (num="0") => num + 42, ~~~~~~~ diff --git a/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.types b/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.types index c7f2b7bbeb007..94aad119feb9b 100644 --- a/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.types +++ b/tests/baselines/reference/checkJsdocTypeTagOnObjectProperty2.types @@ -14,7 +14,7 @@ const obj = { /** @type {function(number): number} */ method1(n1) { ->method1 : (n1: number) => string +>method1 : (n1: number) => number >n1 : number return "42"; @@ -24,7 +24,7 @@ const obj = { /** @type {function(number): number} */ method2: (n1) => "lol", >method2 : (arg0: number) => number ->(n1) => "lol" : (n1: number) => string +>(n1) => "lol" : (n1: number) => number >n1 : number >"lol" : "lol" diff --git a/tests/baselines/reference/typedefTagTypeResolution.types b/tests/baselines/reference/typedefTagTypeResolution.types index 20c9412832667..c5c6021b1da38 100644 --- a/tests/baselines/reference/typedefTagTypeResolution.types +++ b/tests/baselines/reference/typedefTagTypeResolution.types @@ -35,6 +35,6 @@ function g(vvvvv) { /** @type {Cb} */ const cb = x => {} >cb : Cb ->x => {} : (x: any) => void +>x => {} : (x: any) => any >x : any diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts b/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts index f56b99b9e99e9..ecd597c6eb5da 100644 --- a/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts +++ b/tests/cases/conformance/jsdoc/checkJsdocTypeTag5.ts @@ -16,3 +16,23 @@ function i(x) { return x } var j = x => x /** @type {{ (x: number): string }} */ var k = function (x) { return x } + + +/** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */ +/** @type {Argle} */ +function blargle(s) { + return 0; +} + +/** @type {0 | 1 | 2} - assignment should not error */ +var zeroonetwo = blargle('hi') + +/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */ + +/** @type {Gioconda} */ +function monaLisa(sb) { + return typeof sb === 'string' ? 1 : 2; +} + +/** @type {2 | 3} - overloads are not supported, so there will be an error */ +var twothree = monaLisa(false); diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypeTag6.ts b/tests/cases/conformance/jsdoc/checkJsdocTypeTag6.ts new file mode 100644 index 0000000000000..641ac08e56ceb --- /dev/null +++ b/tests/cases/conformance/jsdoc/checkJsdocTypeTag6.ts @@ -0,0 +1,13 @@ +// @checkJs: true +// @allowJs: true +// @noEmit: true +// @Filename: test.js + +/** @type {number} */ +function f() { + return 1 +} + +/** @type {{ prop: string }} */ +var g = function (prop) { +}