fix(45919): allow using JSDoc types for arrow function with type predicate (#45952)

This commit is contained in:
Oleksandr T 2021-09-30 20:50:25 +03:00 committed by GitHub
parent e0f436c628
commit d613748932
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 178 additions and 8 deletions

View file

@ -23206,10 +23206,10 @@ namespace ts {
return isLengthPushOrUnshift || isElementAssignment;
}
function isDeclarationWithExplicitTypeAnnotation(declaration: Declaration) {
return (declaration.kind === SyntaxKind.VariableDeclaration || declaration.kind === SyntaxKind.Parameter ||
declaration.kind === SyntaxKind.PropertyDeclaration || declaration.kind === SyntaxKind.PropertySignature) &&
!!getEffectiveTypeAnnotationNode(declaration as VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature);
function isDeclarationWithExplicitTypeAnnotation(node: Declaration) {
return (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isParameter(node)) &&
!!(getEffectiveTypeAnnotationNode(node) ||
isInJSFile(node) && hasInitializer(node) && node.initializer && isFunctionExpressionOrArrowFunction(node.initializer) && getEffectiveReturnTypeNode(node.initializer));
}
function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) {
@ -26570,10 +26570,6 @@ namespace ts {
return !hasEffectiveRestParameter(signature) && getParameterCount(signature) < targetParameterCount;
}
function isFunctionExpressionOrArrowFunction(node: Node): node is FunctionExpression | ArrowFunction {
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
}
function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature | undefined {
// Only function expressions, arrow functions, and object literal methods are contextually typed.
return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node)

View file

@ -7415,4 +7415,8 @@ namespace ts {
const declaration = symbol.valueDeclaration && getRootDeclaration(symbol.valueDeclaration);
return !!declaration && (isParameter(declaration) || isCatchClauseVariableDeclaration(declaration));
}
export function isFunctionExpressionOrArrowFunction(node: Node): node is FunctionExpression | ArrowFunction {
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
}
}

View file

@ -0,0 +1,50 @@
//// [assertionTypePredicates2.js]
/**
* @typedef {{ x: number }} A
*/
/**
* @typedef { A & { y: number } } B
*/
/**
* @param {A} a
* @returns { asserts a is B }
*/
const foo = (a) => {
if (/** @type { B } */ (a).y !== 0) throw TypeError();
return undefined;
};
export const main = () => {
/** @type { A } */
const a = { x: 1 };
foo(a);
};
//// [assertionTypePredicates2.js]
"use strict";
/**
* @typedef {{ x: number }} A
*/
exports.__esModule = true;
exports.main = void 0;
/**
* @typedef { A & { y: number } } B
*/
/**
* @param {A} a
* @returns { asserts a is B }
*/
var foo = function (a) {
if ( /** @type { B } */(a).y !== 0)
throw TypeError();
return undefined;
};
var main = function () {
/** @type { A } */
var a = { x: 1 };
foo(a);
};
exports.main = main;

View file

@ -0,0 +1,42 @@
=== tests/cases/conformance/controlFlow/assertionTypePredicates2.js ===
/**
* @typedef {{ x: number }} A
*/
/**
* @typedef { A & { y: number } } B
*/
/**
* @param {A} a
* @returns { asserts a is B }
*/
const foo = (a) => {
>foo : Symbol(foo, Decl(assertionTypePredicates2.js, 12, 5))
>a : Symbol(a, Decl(assertionTypePredicates2.js, 12, 13))
if (/** @type { B } */ (a).y !== 0) throw TypeError();
>(a).y : Symbol(y, Decl(assertionTypePredicates2.js, 5, 19))
>a : Symbol(a, Decl(assertionTypePredicates2.js, 12, 13))
>y : Symbol(y, Decl(assertionTypePredicates2.js, 5, 19))
>TypeError : Symbol(TypeError, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
return undefined;
>undefined : Symbol(undefined)
};
export const main = () => {
>main : Symbol(main, Decl(assertionTypePredicates2.js, 17, 12))
/** @type { A } */
const a = { x: 1 };
>a : Symbol(a, Decl(assertionTypePredicates2.js, 19, 9))
>x : Symbol(x, Decl(assertionTypePredicates2.js, 19, 15))
foo(a);
>foo : Symbol(foo, Decl(assertionTypePredicates2.js, 12, 5))
>a : Symbol(a, Decl(assertionTypePredicates2.js, 19, 9))
};

View file

@ -0,0 +1,51 @@
=== tests/cases/conformance/controlFlow/assertionTypePredicates2.js ===
/**
* @typedef {{ x: number }} A
*/
/**
* @typedef { A & { y: number } } B
*/
/**
* @param {A} a
* @returns { asserts a is B }
*/
const foo = (a) => {
>foo : (a: A) => asserts a is B
>(a) => { if (/** @type { B } */ (a).y !== 0) throw TypeError(); return undefined;} : (a: A) => asserts a is B
>a : A
if (/** @type { B } */ (a).y !== 0) throw TypeError();
>(a).y !== 0 : boolean
>(a).y : number
>(a) : B
>a : A
>y : number
>0 : 0
>TypeError() : TypeError
>TypeError : TypeErrorConstructor
return undefined;
>undefined : undefined
};
export const main = () => {
>main : () => void
>() => { /** @type { A } */ const a = { x: 1 }; foo(a);} : () => void
/** @type { A } */
const a = { x: 1 };
>a : A
>{ x: 1 } : { x: number; }
>x : number
>1 : 1
foo(a);
>foo(a) : void
>foo : (a: A) => asserts a is B
>a : A
};

View file

@ -0,0 +1,27 @@
// @allowJs: true
// @checkJs: true
// @outDir: ./out
// @filename: assertionTypePredicates2.js
/**
* @typedef {{ x: number }} A
*/
/**
* @typedef { A & { y: number } } B
*/
/**
* @param {A} a
* @returns { asserts a is B }
*/
const foo = (a) => {
if (/** @type { B } */ (a).y !== 0) throw TypeError();
return undefined;
};
export const main = () => {
/** @type { A } */
const a = { x: 1 };
foo(a);
};