mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Get return type from @type tag (#25580)
* Get return type from `@type` tag This only happens in the checker, where the type is easily accessible. The syntax-based check in getEffectiveReturnTypeNode as a fast path, and for other uses that don't want to make a call to getTypeFromTypeNode. Fixes #25525 * Implement PR suggestions * Error when type tag isn't callable * Fix lint
This commit is contained in:
+33
-16
@@ -7566,12 +7566,21 @@ namespace ts {
|
||||
const setter = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(declaration), SyntaxKind.SetAccessor);
|
||||
return getAnnotatedAccessorType(setter);
|
||||
}
|
||||
|
||||
const typeFromTag = getReturnTypeOfTypeTag(declaration);
|
||||
if (typeFromTag) {
|
||||
return typeFromTag;
|
||||
}
|
||||
if (nodeIsMissing((<FunctionLikeDeclaration>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) {
|
||||
@@ -20539,15 +20548,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
|
||||
@@ -20555,7 +20569,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
|
||||
@@ -22007,7 +22021,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) {
|
||||
checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node);
|
||||
checkAsyncFunctionReturnType(<FunctionLikeDeclaration>node, returnTypeNode);
|
||||
}
|
||||
}
|
||||
if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) {
|
||||
@@ -23067,7 +23081,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
|
||||
@@ -23092,7 +23106,6 @@ namespace ts {
|
||||
// then<U>(...): Promise<U>;
|
||||
// }
|
||||
//
|
||||
const returnTypeNode = getEffectiveReturnTypeNode(node)!; // TODO: GH#18217
|
||||
const returnType = getTypeFromTypeNode(returnTypeNode);
|
||||
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
@@ -23502,15 +23515,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)) {
|
||||
@@ -23523,6 +23533,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24785,7 +24802,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);
|
||||
|
||||
@@ -4021,6 +4021,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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -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
|
||||
|
||||
@@ -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'.
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'.
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
~~~~~~~
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -35,6 +35,6 @@ function g(vvvvv) {
|
||||
/** @type {Cb} */
|
||||
const cb = x => {}
|
||||
>cb : Cb
|
||||
>x => {} : (x: any) => void
|
||||
>x => {} : (x: any) => any
|
||||
>x : any
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
Reference in New Issue
Block a user