mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
JSDoc @type tag optional parameters (#48132)
* JSDoc @type tag optional parameters * Don't repeat isInJSFile() condition * Exclude variable initializers * Add tests for class methods * Don't contextually type JS function declarations * Update Baselines and/or Applied Lint Fixes * Reword comment Co-authored-by: TypeScript Bot <typescriptbot@microsoft.com>
This commit is contained in:
co-authored by
TypeScript Bot
parent
2513a2d98c
commit
35c6fbfee0
+13
-9
@@ -9065,10 +9065,8 @@ namespace ts {
|
||||
return getReturnTypeOfSignature(getterSignature);
|
||||
}
|
||||
}
|
||||
if (isInJSFile(declaration)) {
|
||||
const type = getParameterTypeOfTypeTag(func, declaration);
|
||||
if (type) return type;
|
||||
}
|
||||
const parameterTypeOfTypeTag = getParameterTypeOfTypeTag(func, declaration);
|
||||
if (parameterTypeOfTypeTag) return parameterTypeOfTypeTag;
|
||||
// Use contextual parameter type if one is available
|
||||
const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration);
|
||||
if (type) {
|
||||
@@ -13117,7 +13115,14 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.push(getSignatureFromDeclaration(decl));
|
||||
// If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters.
|
||||
// Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would supress checks that the two are compatible.
|
||||
result.push(
|
||||
(!isFunctionExpressionOrArrowFunction(decl) &&
|
||||
!isObjectLiteralMethod(decl) &&
|
||||
getSignatureOfTypeTag(decl)) ||
|
||||
getSignatureFromDeclaration(decl)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -13152,7 +13157,7 @@ namespace ts {
|
||||
else {
|
||||
const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration);
|
||||
let jsdocPredicate: TypePredicate | undefined;
|
||||
if (!type && isInJSFile(signature.declaration)) {
|
||||
if (!type) {
|
||||
const jsdocSignature = getSignatureOfTypeTag(signature.declaration!);
|
||||
if (jsdocSignature && signature !== jsdocSignature) {
|
||||
jsdocPredicate = getTypePredicateOfSignature(jsdocSignature);
|
||||
@@ -17470,8 +17475,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
|
||||
return (!isFunctionDeclaration(node) || isInJSFile(node) && !!getTypeForDeclarationFromJSDocComment(node)) &&
|
||||
(hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node));
|
||||
return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node);
|
||||
}
|
||||
|
||||
function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) {
|
||||
@@ -17480,7 +17484,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
|
||||
return (isInJSFile(func) && isFunctionDeclaration(func) || isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) &&
|
||||
return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) &&
|
||||
isContextSensitiveFunctionLikeDeclaration(func);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ var k = function (x) { return x }
|
||||
/** @typedef {(x: 'hi' | 'bye') => 0 | 1 | 2} Argle */
|
||||
/** @type {Argle} */
|
||||
function blargle(s) {
|
||||
>blargle : (s: "hi" | "bye") => 0 | 1 | 2
|
||||
>blargle : (x: 'hi' | 'bye') => 0 | 1 | 2
|
||||
>s : "hi" | "bye"
|
||||
|
||||
return 0;
|
||||
@@ -55,7 +55,7 @@ function blargle(s) {
|
||||
var zeroonetwo = blargle('hi')
|
||||
>zeroonetwo : 0 | 1 | 2
|
||||
>blargle('hi') : 0 | 1 | 2
|
||||
>blargle : (s: "hi" | "bye") => 0 | 1 | 2
|
||||
>blargle : (x: "hi" | "bye") => 0 | 1 | 2
|
||||
>'hi' : "hi"
|
||||
|
||||
/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda */
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
tests/cases/conformance/jsdoc/test.js(1,12): error TS8030: The type of a function declaration must match the function's signature.
|
||||
tests/cases/conformance/jsdoc/test.js(7,5): error TS2322: Type '(prop: any) => void' is not assignable to type '{ prop: string; }'.
|
||||
tests/cases/conformance/jsdoc/test.js(10,12): error TS8030: The type of a function declaration must match the function's signature.
|
||||
tests/cases/conformance/jsdoc/test.js(23,12): error TS8030: The type of a function declaration must match the function's signature.
|
||||
tests/cases/conformance/jsdoc/test.js(27,7): error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
tests/cases/conformance/jsdoc/test.js(30,7): error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
tests/cases/conformance/jsdoc/test.js(34,3): error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/test.js (3 errors) ====
|
||||
==== tests/cases/conformance/jsdoc/test.js (7 errors) ====
|
||||
/** @type {number} */
|
||||
~~~~~~
|
||||
!!! error TS8030: The type of a function declaration must match the function's signature.
|
||||
@@ -28,4 +32,29 @@ tests/cases/conformance/jsdoc/test.js(10,12): error TS8030: The type of a functi
|
||||
// TODO: Should be an error since signature doesn't match.
|
||||
/** @type {(a: number, b: number, c: number) => number} */
|
||||
function add3(a, b) { return a + b; }
|
||||
|
||||
// Confirm initializers are compatible.
|
||||
// They can't have more parameters than the type/context.
|
||||
|
||||
/** @type {() => void} */
|
||||
~~~~~~~~~~
|
||||
!!! error TS8030: The type of a function declaration must match the function's signature.
|
||||
function funcWithMoreParameters(more) {} // error
|
||||
|
||||
/** @type {() => void} */
|
||||
const variableWithMoreParameters = function (more) {}; // error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
|
||||
/** @type {() => void} */
|
||||
const arrowWithMoreParameters = (more) => {}; // error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
|
||||
({
|
||||
/** @type {() => void} */
|
||||
methodWithMoreParameters(more) {}, // error
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '(more: any) => void' is not assignable to type '() => void'.
|
||||
});
|
||||
|
||||
@@ -37,3 +37,29 @@ function add3(a, b) { return a + b; }
|
||||
>a : Symbol(a, Decl(test.js, 17, 14))
|
||||
>b : Symbol(b, Decl(test.js, 17, 16))
|
||||
|
||||
// Confirm initializers are compatible.
|
||||
// They can't have more parameters than the type/context.
|
||||
|
||||
/** @type {() => void} */
|
||||
function funcWithMoreParameters(more) {} // error
|
||||
>funcWithMoreParameters : Symbol(funcWithMoreParameters, Decl(test.js, 17, 37))
|
||||
>more : Symbol(more, Decl(test.js, 23, 32))
|
||||
|
||||
/** @type {() => void} */
|
||||
const variableWithMoreParameters = function (more) {}; // error
|
||||
>variableWithMoreParameters : Symbol(variableWithMoreParameters, Decl(test.js, 26, 5))
|
||||
>more : Symbol(more, Decl(test.js, 26, 45))
|
||||
|
||||
/** @type {() => void} */
|
||||
const arrowWithMoreParameters = (more) => {}; // error
|
||||
>arrowWithMoreParameters : Symbol(arrowWithMoreParameters, Decl(test.js, 29, 5))
|
||||
>more : Symbol(more, Decl(test.js, 29, 33))
|
||||
|
||||
({
|
||||
/** @type {() => void} */
|
||||
methodWithMoreParameters(more) {}, // error
|
||||
>methodWithMoreParameters : Symbol(methodWithMoreParameters, Decl(test.js, 31, 2))
|
||||
>more : Symbol(more, Decl(test.js, 33, 27))
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ var g = function (prop) {
|
||||
|
||||
/** @type {(a: number) => number} */
|
||||
function add1(a, b) { return a + b; }
|
||||
>add1 : (a: number, b: any) => number
|
||||
>add1 : (a: number) => number
|
||||
>a : number
|
||||
>b : any
|
||||
>a + b : any
|
||||
@@ -35,10 +35,41 @@ function add2(a, b) { return a + b; }
|
||||
// TODO: Should be an error since signature doesn't match.
|
||||
/** @type {(a: number, b: number, c: number) => number} */
|
||||
function add3(a, b) { return a + b; }
|
||||
>add3 : (a: number, b: number) => number
|
||||
>add3 : (a: number, b: number, c: number) => number
|
||||
>a : number
|
||||
>b : number
|
||||
>a + b : number
|
||||
>a : number
|
||||
>b : number
|
||||
|
||||
// Confirm initializers are compatible.
|
||||
// They can't have more parameters than the type/context.
|
||||
|
||||
/** @type {() => void} */
|
||||
function funcWithMoreParameters(more) {} // error
|
||||
>funcWithMoreParameters : () => void
|
||||
>more : any
|
||||
|
||||
/** @type {() => void} */
|
||||
const variableWithMoreParameters = function (more) {}; // error
|
||||
>variableWithMoreParameters : () => void
|
||||
>function (more) {} : (more: any) => void
|
||||
>more : any
|
||||
|
||||
/** @type {() => void} */
|
||||
const arrowWithMoreParameters = (more) => {}; // error
|
||||
>arrowWithMoreParameters : () => void
|
||||
>(more) => {} : (more: any) => void
|
||||
>more : any
|
||||
|
||||
({
|
||||
>({ /** @type {() => void} */ methodWithMoreParameters(more) {}, // error}) : { methodWithMoreParameters(): void; }
|
||||
>{ /** @type {() => void} */ methodWithMoreParameters(more) {}, // error} : { methodWithMoreParameters(): void; }
|
||||
|
||||
/** @type {() => void} */
|
||||
methodWithMoreParameters(more) {}, // error
|
||||
>methodWithMoreParameters : (more: any) => void
|
||||
>more : any
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -11,5 +11,9 @@ class C {
|
||||
>foo : Symbol(C.foo, Decl(test.js, 4, 9))
|
||||
>a : Symbol(a, Decl(test.js, 6, 8))
|
||||
>b : Symbol(b, Decl(test.js, 6, 10))
|
||||
|
||||
/** @type {(optional?) => void} */
|
||||
methodWithOptionalParameters() {}
|
||||
>methodWithOptionalParameters : Symbol(C.methodWithOptionalParameters, Decl(test.js, 6, 16))
|
||||
}
|
||||
|
||||
|
||||
@@ -11,5 +11,9 @@ class C {
|
||||
>foo : (a: string, b: number) => void
|
||||
>a : string
|
||||
>b : number
|
||||
|
||||
/** @type {(optional?) => void} */
|
||||
methodWithOptionalParameters() {}
|
||||
>methodWithOptionalParameters : (optional?: any) => void
|
||||
}
|
||||
|
||||
|
||||
@@ -181,19 +181,82 @@
|
||||
"kind": "space"
|
||||
}
|
||||
],
|
||||
"parameters": [],
|
||||
"documentation": [],
|
||||
"tags": [
|
||||
"parameters": [
|
||||
{
|
||||
"name": "type",
|
||||
"text": [
|
||||
"name": "arg0",
|
||||
"documentation": [],
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "{function(module:xxxx, module:xxxx): module:xxxxx}",
|
||||
"kind": "text"
|
||||
"text": "arg0",
|
||||
"kind": "parameterName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "any",
|
||||
"kind": "keyword"
|
||||
}
|
||||
]
|
||||
],
|
||||
"isOptional": false,
|
||||
"isRest": false
|
||||
},
|
||||
{
|
||||
"name": "arg1",
|
||||
"documentation": [],
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "arg1",
|
||||
"kind": "parameterName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "any",
|
||||
"kind": "keyword"
|
||||
}
|
||||
],
|
||||
"isOptional": false,
|
||||
"isRest": false
|
||||
},
|
||||
{
|
||||
"name": "arg2",
|
||||
"documentation": [],
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "arg2",
|
||||
"kind": "parameterName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "any",
|
||||
"kind": "keyword"
|
||||
}
|
||||
],
|
||||
"isOptional": false,
|
||||
"isRest": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"documentation": [],
|
||||
"tags": []
|
||||
}
|
||||
],
|
||||
"applicableSpan": {
|
||||
|
||||
@@ -21,9 +21,9 @@ tests/cases/conformance/jsdoc/a.js(13,1): error TS2554: Expected 1 arguments, bu
|
||||
g() // should error
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/jsdoc/a.js:5:12: An argument for 's' was not provided.
|
||||
!!! related TS6210 tests/cases/conformance/jsdoc/a.js:4:13: An argument for 's' was not provided.
|
||||
h()
|
||||
~~~
|
||||
!!! error TS2554: Expected 1 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/jsdoc/a.js:8:12: An argument for 's' was not provided.
|
||||
!!! related TS6210 tests/cases/conformance/jsdoc/a.js:7:14: An argument for 's' was not provided.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
=== tests/cases/conformance/jsdoc/bug25618.js ===
|
||||
/** @type {<T>(param?: T) => T | undefined} */
|
||||
function typed(param) {
|
||||
>typed : <T>(param: T | undefined) => T | undefined
|
||||
>typed : <T>(param?: T | undefined) => T | undefined
|
||||
>param : T | undefined
|
||||
|
||||
return param;
|
||||
@@ -11,7 +11,7 @@ function typed(param) {
|
||||
var n = typed(1);
|
||||
>n : number | undefined
|
||||
>typed(1) : 1 | undefined
|
||||
>typed : <T>(param: T | undefined) => T | undefined
|
||||
>typed : <T>(param?: T | undefined) => T | undefined
|
||||
>1 : 1
|
||||
|
||||
|
||||
|
||||
@@ -21,3 +21,20 @@ function add2(a, b) { return a + b; }
|
||||
// TODO: Should be an error since signature doesn't match.
|
||||
/** @type {(a: number, b: number, c: number) => number} */
|
||||
function add3(a, b) { return a + b; }
|
||||
|
||||
// Confirm initializers are compatible.
|
||||
// They can't have more parameters than the type/context.
|
||||
|
||||
/** @type {() => void} */
|
||||
function funcWithMoreParameters(more) {} // error
|
||||
|
||||
/** @type {() => void} */
|
||||
const variableWithMoreParameters = function (more) {}; // error
|
||||
|
||||
/** @type {() => void} */
|
||||
const arrowWithMoreParameters = (more) => {}; // error
|
||||
|
||||
({
|
||||
/** @type {() => void} */
|
||||
methodWithMoreParameters(more) {}, // error
|
||||
});
|
||||
|
||||
@@ -10,4 +10,7 @@
|
||||
class C {
|
||||
/** @type {Foo} */
|
||||
foo(a, b) {}
|
||||
|
||||
/** @type {(optional?) => void} */
|
||||
methodWithOptionalParameters() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user