mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
fix(39836): allow type declaration/unknown type in catch arguments in JavaScript files (#42392)
This commit is contained in:
parent
38fdce9440
commit
ca8d9e4402
@ -8847,9 +8847,11 @@ namespace ts {
|
||||
Debug.assertIsDefined(symbol.valueDeclaration);
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) {
|
||||
const decl = declaration as VariableDeclaration;
|
||||
if (!decl.type) return anyType;
|
||||
const type = getTypeOfNode(decl.type);
|
||||
const typeNode = getEffectiveTypeAnnotationNode(declaration);
|
||||
if (typeNode === undefined) {
|
||||
return anyType;
|
||||
}
|
||||
const type = getTypeOfNode(typeNode);
|
||||
// an errorType will make `checkTryStatement` issue an error
|
||||
return isTypeAny(type) || type === unknownType ? type : errorType;
|
||||
}
|
||||
@ -36044,10 +36046,11 @@ namespace ts {
|
||||
// Grammar checking
|
||||
if (catchClause.variableDeclaration) {
|
||||
const declaration = catchClause.variableDeclaration;
|
||||
if (declaration.type) {
|
||||
const typeNode = getEffectiveTypeAnnotationNode(getRootDeclaration(declaration));
|
||||
if (typeNode) {
|
||||
const type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ false);
|
||||
if (type && !(type.flags & TypeFlags.AnyOrUnknown)) {
|
||||
grammarErrorOnFirstToken(declaration.type, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified);
|
||||
grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified);
|
||||
}
|
||||
}
|
||||
else if (declaration.initializer) {
|
||||
|
||||
@ -6279,6 +6279,7 @@ namespace ts {
|
||||
|
||||
function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
|
||||
const pos = getNodePos();
|
||||
const hasJSDoc = hasPrecedingJSDocComment();
|
||||
const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations);
|
||||
let exclamationToken: ExclamationToken | undefined;
|
||||
if (allowExclamation && name.kind === SyntaxKind.Identifier &&
|
||||
@ -6288,7 +6289,7 @@ namespace ts {
|
||||
const type = parseTypeAnnotation();
|
||||
const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer();
|
||||
const node = factory.createVariableDeclaration(name, exclamationToken, type, initializer);
|
||||
return finishNode(node, pos);
|
||||
return withJSDoc(finishNode(node, pos), hasJSDoc);
|
||||
}
|
||||
|
||||
function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList {
|
||||
|
||||
@ -874,6 +874,7 @@ namespace ts {
|
||||
| FunctionDeclaration
|
||||
| ConstructorDeclaration
|
||||
| MethodDeclaration
|
||||
| VariableDeclaration
|
||||
| PropertyDeclaration
|
||||
| AccessorDeclaration
|
||||
| ClassLikeDeclaration
|
||||
@ -1237,7 +1238,7 @@ namespace ts {
|
||||
|
||||
export type BindingName = Identifier | BindingPattern;
|
||||
|
||||
export interface VariableDeclaration extends NamedDeclaration {
|
||||
export interface VariableDeclaration extends NamedDeclaration, JSDocContainer {
|
||||
readonly kind: SyntaxKind.VariableDeclaration;
|
||||
readonly parent: VariableDeclarationList | CatchClause;
|
||||
readonly name: BindingName; // Declared variable name
|
||||
|
||||
@ -1204,7 +1204,8 @@ namespace ts {
|
||||
node.kind === SyntaxKind.TypeParameter ||
|
||||
node.kind === SyntaxKind.FunctionExpression ||
|
||||
node.kind === SyntaxKind.ArrowFunction ||
|
||||
node.kind === SyntaxKind.ParenthesizedExpression) ?
|
||||
node.kind === SyntaxKind.ParenthesizedExpression ||
|
||||
node.kind === SyntaxKind.VariableDeclaration) ?
|
||||
concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) :
|
||||
getLeadingCommentRanges(text, node.pos);
|
||||
// True if the comment starts with '/**' but not if it is '/**/'
|
||||
|
||||
@ -558,7 +558,7 @@ declare namespace ts {
|
||||
}
|
||||
export interface JSDocContainer {
|
||||
}
|
||||
export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | EndOfFileToken;
|
||||
export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | VariableDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | EndOfFileToken;
|
||||
export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType;
|
||||
export type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement;
|
||||
export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute;
|
||||
@ -687,7 +687,7 @@ declare namespace ts {
|
||||
readonly kind: SyntaxKind.ConstructSignature;
|
||||
}
|
||||
export type BindingName = Identifier | BindingPattern;
|
||||
export interface VariableDeclaration extends NamedDeclaration {
|
||||
export interface VariableDeclaration extends NamedDeclaration, JSDocContainer {
|
||||
readonly kind: SyntaxKind.VariableDeclaration;
|
||||
readonly parent: VariableDeclarationList | CatchClause;
|
||||
readonly name: BindingName;
|
||||
|
||||
@ -558,7 +558,7 @@ declare namespace ts {
|
||||
}
|
||||
export interface JSDocContainer {
|
||||
}
|
||||
export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | EndOfFileToken;
|
||||
export type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | VariableDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | EndOfFileToken;
|
||||
export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType;
|
||||
export type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement;
|
||||
export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute;
|
||||
@ -687,7 +687,7 @@ declare namespace ts {
|
||||
readonly kind: SyntaxKind.ConstructSignature;
|
||||
}
|
||||
export type BindingName = Identifier | BindingPattern;
|
||||
export interface VariableDeclaration extends NamedDeclaration {
|
||||
export interface VariableDeclaration extends NamedDeclaration, JSDocContainer {
|
||||
readonly kind: SyntaxKind.VariableDeclaration;
|
||||
readonly parent: VariableDeclarationList | CatchClause;
|
||||
readonly name: BindingName;
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
tests/cases/conformance/jsdoc/foo.js(20,54): error TS2339: Property 'foo' does not exist on type 'unknown'.
|
||||
tests/cases/conformance/jsdoc/foo.js(21,54): error TS2339: Property 'foo' does not exist on type 'unknown'.
|
||||
tests/cases/conformance/jsdoc/foo.js(22,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
tests/cases/conformance/jsdoc/foo.js(23,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
tests/cases/conformance/jsdoc/foo.js(35,7): error TS2492: Cannot redeclare identifier 'err' in catch clause.
|
||||
tests/cases/conformance/jsdoc/foo.js(48,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
tests/cases/conformance/jsdoc/foo.js(49,31): error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/foo.js (7 errors) ====
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
|
||||
function fn() {
|
||||
try { } catch (x) { } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { } // should be OK
|
||||
try { } catch (err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { err.foo; } // error in the body
|
||||
~~~
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
|
||||
try { } catch (/** @type {Unknown} */ err) { err.foo; } // error in the body
|
||||
~~~
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'unknown'.
|
||||
try { } catch (/** @type {Error} */ err) { } // error in the type
|
||||
~~~~~
|
||||
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
try { } catch (/** @type {object} */ err) { } // error in the type
|
||||
~~~~~~
|
||||
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
|
||||
try { console.log(); }
|
||||
// @ts-ignore
|
||||
catch (/** @type {number} */ err) { // e should not be a `number`
|
||||
console.log(err.toLowerCase());
|
||||
}
|
||||
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {string} */
|
||||
let err;
|
||||
~~~
|
||||
!!! error TS2492: Cannot redeclare identifier 'err' in catch clause.
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
}
|
||||
|
||||
try { } catch ({ x }) { } // should be OK
|
||||
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
|
||||
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Error} */ { x }) { } // error in the type
|
||||
~~~~~
|
||||
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
try { } catch (/** @type {object} */ { x }) { } // error in the type
|
||||
~~~~~~
|
||||
!!! error TS1196: Catch clause variable type annotation must be 'any' or 'unknown' if specified.
|
||||
}
|
||||
|
||||
144
tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.js
Normal file
144
tests/baselines/reference/jsdocCatchClauseWithTypeAnnotation.js
Normal file
@ -0,0 +1,144 @@
|
||||
//// [foo.js]
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
|
||||
function fn() {
|
||||
try { } catch (x) { } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { } // should be OK
|
||||
try { } catch (err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { err.foo; } // error in the body
|
||||
try { } catch (/** @type {Unknown} */ err) { err.foo; } // error in the body
|
||||
try { } catch (/** @type {Error} */ err) { } // error in the type
|
||||
try { } catch (/** @type {object} */ err) { } // error in the type
|
||||
|
||||
try { console.log(); }
|
||||
// @ts-ignore
|
||||
catch (/** @type {number} */ err) { // e should not be a `number`
|
||||
console.log(err.toLowerCase());
|
||||
}
|
||||
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {string} */
|
||||
let err;
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
}
|
||||
|
||||
try { } catch ({ x }) { } // should be OK
|
||||
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
|
||||
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Error} */ { x }) { } // error in the type
|
||||
try { } catch (/** @type {object} */ { x }) { } // error in the type
|
||||
}
|
||||
|
||||
|
||||
//// [foo.js]
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
function fn() {
|
||||
try { }
|
||||
catch (x) { } // should be OK
|
||||
try { }
|
||||
catch ( /** @type {any} */err) { } // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Any} */err) { } // should be OK
|
||||
try { }
|
||||
catch ( /** @type {unknown} */err) { } // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Unknown} */err) { } // should be OK
|
||||
try { }
|
||||
catch (err) {
|
||||
err.foo;
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {any} */err) {
|
||||
err.foo;
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Any} */err) {
|
||||
err.foo;
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {unknown} */err) {
|
||||
console.log(err);
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Unknown} */err) {
|
||||
console.log(err);
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {unknown} */err) {
|
||||
err.foo;
|
||||
} // error in the body
|
||||
try { }
|
||||
catch ( /** @type {Unknown} */err) {
|
||||
err.foo;
|
||||
} // error in the body
|
||||
try { }
|
||||
catch ( /** @type {Error} */err) { } // error in the type
|
||||
try { }
|
||||
catch ( /** @type {object} */err) { } // error in the type
|
||||
try {
|
||||
console.log();
|
||||
}
|
||||
// @ts-ignore
|
||||
catch ( /** @type {number} */err) { // e should not be a `number`
|
||||
console.log(err.toLowerCase());
|
||||
}
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {string} */
|
||||
let err;
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
}
|
||||
try { }
|
||||
catch ({ x }) { } // should be OK
|
||||
try { }
|
||||
catch ( /** @type {any} */{ x }) {
|
||||
x.foo;
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Any} */{ x }) {
|
||||
x.foo;
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {unknown} */{ x }) {
|
||||
console.log(x);
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Unknown} */{ x }) {
|
||||
console.log(x);
|
||||
} // should be OK
|
||||
try { }
|
||||
catch ( /** @type {Error} */{ x }) { } // error in the type
|
||||
try { }
|
||||
catch ( /** @type {object} */{ x }) { } // error in the type
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
|
||||
function fn() {
|
||||
>fn : Symbol(fn, Decl(foo.js, 0, 0))
|
||||
|
||||
try { } catch (x) { } // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 9, 19))
|
||||
|
||||
try { } catch (/** @type {any} */ err) { } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 10, 19))
|
||||
|
||||
try { } catch (/** @type {Any} */ err) { } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 11, 19))
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 12, 19))
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 13, 19))
|
||||
|
||||
try { } catch (err) { err.foo; } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 14, 19))
|
||||
>err : Symbol(err, Decl(foo.js, 14, 19))
|
||||
|
||||
try { } catch (/** @type {any} */ err) { err.foo; } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 15, 19))
|
||||
>err : Symbol(err, Decl(foo.js, 15, 19))
|
||||
|
||||
try { } catch (/** @type {Any} */ err) { err.foo; } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 16, 19))
|
||||
>err : Symbol(err, Decl(foo.js, 16, 19))
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { console.log(err); } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 17, 19))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>err : Symbol(err, Decl(foo.js, 17, 19))
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { console.log(err); } // should be OK
|
||||
>err : Symbol(err, Decl(foo.js, 18, 19))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>err : Symbol(err, Decl(foo.js, 18, 19))
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { err.foo; } // error in the body
|
||||
>err : Symbol(err, Decl(foo.js, 19, 19))
|
||||
>err : Symbol(err, Decl(foo.js, 19, 19))
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { err.foo; } // error in the body
|
||||
>err : Symbol(err, Decl(foo.js, 20, 19))
|
||||
>err : Symbol(err, Decl(foo.js, 20, 19))
|
||||
|
||||
try { } catch (/** @type {Error} */ err) { } // error in the type
|
||||
>err : Symbol(err, Decl(foo.js, 21, 19))
|
||||
|
||||
try { } catch (/** @type {object} */ err) { } // error in the type
|
||||
>err : Symbol(err, Decl(foo.js, 22, 19))
|
||||
|
||||
try { console.log(); }
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// @ts-ignore
|
||||
catch (/** @type {number} */ err) { // e should not be a `number`
|
||||
>err : Symbol(err, Decl(foo.js, 26, 11))
|
||||
|
||||
console.log(err.toLowerCase());
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>err : Symbol(err, Decl(foo.js, 26, 11))
|
||||
}
|
||||
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
>err : Symbol(err, Decl(foo.js, 32, 8))
|
||||
|
||||
/** @type {string} */
|
||||
let err;
|
||||
>err : Symbol(err, Decl(foo.js, 34, 5))
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
>err : Symbol(err, Decl(foo.js, 37, 8))
|
||||
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
>err : Symbol(err, Decl(foo.js, 39, 5))
|
||||
}
|
||||
|
||||
try { } catch ({ x }) { } // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 42, 20))
|
||||
|
||||
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 43, 39))
|
||||
>x : Symbol(x, Decl(foo.js, 43, 39))
|
||||
|
||||
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 44, 39))
|
||||
>x : Symbol(x, Decl(foo.js, 44, 39))
|
||||
|
||||
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 45, 43))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(foo.js, 45, 43))
|
||||
|
||||
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
|
||||
>x : Symbol(x, Decl(foo.js, 46, 43))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(foo.js, 46, 43))
|
||||
|
||||
try { } catch (/** @type {Error} */ { x }) { } // error in the type
|
||||
>x : Symbol(x, Decl(foo.js, 47, 41))
|
||||
|
||||
try { } catch (/** @type {object} */ { x }) { } // error in the type
|
||||
>x : Symbol(x, Decl(foo.js, 48, 42))
|
||||
}
|
||||
|
||||
@ -0,0 +1,156 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
|
||||
function fn() {
|
||||
>fn : () => void
|
||||
|
||||
try { } catch (x) { } // should be OK
|
||||
>x : any
|
||||
|
||||
try { } catch (/** @type {any} */ err) { } // should be OK
|
||||
>err : any
|
||||
|
||||
try { } catch (/** @type {Any} */ err) { } // should be OK
|
||||
>err : any
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { } // should be OK
|
||||
>err : unknown
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { } // should be OK
|
||||
>err : unknown
|
||||
|
||||
try { } catch (err) { err.foo; } // should be OK
|
||||
>err : any
|
||||
>err.foo : any
|
||||
>err : any
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {any} */ err) { err.foo; } // should be OK
|
||||
>err : any
|
||||
>err.foo : any
|
||||
>err : any
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {Any} */ err) { err.foo; } // should be OK
|
||||
>err : any
|
||||
>err.foo : any
|
||||
>err : any
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { console.log(err); } // should be OK
|
||||
>err : unknown
|
||||
>console.log(err) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>err : unknown
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { console.log(err); } // should be OK
|
||||
>err : unknown
|
||||
>console.log(err) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>err : unknown
|
||||
|
||||
try { } catch (/** @type {unknown} */ err) { err.foo; } // error in the body
|
||||
>err : unknown
|
||||
>err.foo : any
|
||||
>err : unknown
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {Unknown} */ err) { err.foo; } // error in the body
|
||||
>err : unknown
|
||||
>err.foo : any
|
||||
>err : unknown
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {Error} */ err) { } // error in the type
|
||||
>err : any
|
||||
|
||||
try { } catch (/** @type {object} */ err) { } // error in the type
|
||||
>err : any
|
||||
|
||||
try { console.log(); }
|
||||
>console.log() : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
|
||||
// @ts-ignore
|
||||
catch (/** @type {number} */ err) { // e should not be a `number`
|
||||
>err : any
|
||||
|
||||
console.log(err.toLowerCase());
|
||||
>console.log(err.toLowerCase()) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>err.toLowerCase() : any
|
||||
>err.toLowerCase : any
|
||||
>err : any
|
||||
>toLowerCase : any
|
||||
}
|
||||
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
>err : any
|
||||
|
||||
/** @type {string} */
|
||||
let err;
|
||||
>err : string
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
>err : any
|
||||
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
>err : boolean
|
||||
}
|
||||
|
||||
try { } catch ({ x }) { } // should be OK
|
||||
>x : any
|
||||
|
||||
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
|
||||
>x : any
|
||||
>x.foo : any
|
||||
>x : any
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
|
||||
>x : any
|
||||
>x.foo : any
|
||||
>x : any
|
||||
>foo : any
|
||||
|
||||
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
|
||||
>x : any
|
||||
>console.log(x) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>x : any
|
||||
|
||||
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
|
||||
>x : any
|
||||
>console.log(x) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>x : any
|
||||
|
||||
try { } catch (/** @type {Error} */ { x }) { } // error in the type
|
||||
>x : any
|
||||
|
||||
try { } catch (/** @type {object} */ { x }) { } // error in the type
|
||||
>x : any
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
//// [foo.js]
|
||||
/** @type {boolean} */
|
||||
var /** @type {string} */ x,
|
||||
/** @type {number} */ y;
|
||||
|
||||
|
||||
//// [foo.js]
|
||||
/** @type {boolean} */
|
||||
var /** @type {string} */ x,
|
||||
/** @type {number} */ y;
|
||||
@ -0,0 +1,8 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/** @type {boolean} */
|
||||
var /** @type {string} */ x,
|
||||
>x : Symbol(x, Decl(foo.js, 1, 3))
|
||||
|
||||
/** @type {number} */ y;
|
||||
>y : Symbol(y, Decl(foo.js, 1, 28))
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
=== tests/cases/conformance/jsdoc/foo.js ===
|
||||
/** @type {boolean} */
|
||||
var /** @type {string} */ x,
|
||||
>x : string
|
||||
|
||||
/** @type {number} */ y;
|
||||
>y : number
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @target: esnext
|
||||
// @noImplicitAny: true
|
||||
// @outDir: out
|
||||
// @Filename: foo.js
|
||||
|
||||
/**
|
||||
* @typedef {any} Any
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {unknown} Unknown
|
||||
*/
|
||||
|
||||
function fn() {
|
||||
try { } catch (x) { } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { } // should be OK
|
||||
try { } catch (err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ err) { err.foo; } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ err) { console.log(err); } // should be OK
|
||||
try { } catch (/** @type {unknown} */ err) { err.foo; } // error in the body
|
||||
try { } catch (/** @type {Unknown} */ err) { err.foo; } // error in the body
|
||||
try { } catch (/** @type {Error} */ err) { } // error in the type
|
||||
try { } catch (/** @type {object} */ err) { } // error in the type
|
||||
|
||||
try { console.log(); }
|
||||
// @ts-ignore
|
||||
catch (/** @type {number} */ err) { // e should not be a `number`
|
||||
console.log(err.toLowerCase());
|
||||
}
|
||||
|
||||
// minor bug: shows that the `catch` argument is skipped when checking scope
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {string} */
|
||||
let err;
|
||||
}
|
||||
try { }
|
||||
catch (err) {
|
||||
/** @type {boolean} */
|
||||
var err;
|
||||
}
|
||||
|
||||
try { } catch ({ x }) { } // should be OK
|
||||
try { } catch (/** @type {any} */ { x }) { x.foo; } // should be OK
|
||||
try { } catch (/** @type {Any} */ { x }) { x.foo;} // should be OK
|
||||
try { } catch (/** @type {unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Unknown} */ { x }) { console.log(x); } // should be OK
|
||||
try { } catch (/** @type {Error} */ { x }) { } // error in the type
|
||||
try { } catch (/** @type {object} */ { x }) { } // error in the type
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @target: esnext
|
||||
// @noImplicitAny: true
|
||||
// @outDir: out
|
||||
// @Filename: foo.js
|
||||
|
||||
/** @type {boolean} */
|
||||
var /** @type {string} */ x,
|
||||
/** @type {number} */ y;
|
||||
Loading…
x
Reference in New Issue
Block a user