mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 07:29:16 -05:00
Verify JS function is constructor
This commit is contained in:
@@ -15892,7 +15892,7 @@ namespace ts {
|
||||
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
|
||||
if (callSignatures.length) {
|
||||
const signature = resolveCall(node, callSignatures, candidatesOutArray);
|
||||
if (!isInJavaScriptFile(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
|
||||
if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
|
||||
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
|
||||
}
|
||||
if (getThisTypeOfSignature(signature) === voidType) {
|
||||
@@ -16119,6 +16119,26 @@ namespace ts {
|
||||
return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a declaration can be treated as a constructor in a JavaScript
|
||||
* file.
|
||||
*/
|
||||
function isJavaScriptConstructor(node: Declaration): boolean {
|
||||
if (isInJavaScriptFile(node)) {
|
||||
// If the node has a @class tag, treat it like a constructor.
|
||||
if (getJSDocClassTag(node)) return true;
|
||||
|
||||
// If the symbol of the node has members, treat it like a constructor.
|
||||
const symbol = isFunctionDeclaration(node) || isFunctionExpression(node) ? getSymbolOfNode(node) :
|
||||
isVariableDeclaration(node) && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) :
|
||||
undefined;
|
||||
|
||||
return symbol && symbol.members !== undefined;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getInferredClassType(symbol: Symbol) {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.inferredClassType) {
|
||||
|
||||
@@ -6533,6 +6533,10 @@ namespace ts {
|
||||
case "augments":
|
||||
tag = parseAugmentsTag(atToken, tagName);
|
||||
break;
|
||||
case "class":
|
||||
case "constructor":
|
||||
tag = parseClassTag(atToken, tagName);
|
||||
break;
|
||||
case "arg":
|
||||
case "argument":
|
||||
case "param":
|
||||
@@ -6752,6 +6756,13 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
|
||||
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
|
||||
tag.atToken = atToken;
|
||||
tag.tagName = tagName;
|
||||
return finishNode(tag);
|
||||
}
|
||||
|
||||
function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
@@ -374,6 +374,7 @@ namespace ts {
|
||||
JSDocComment,
|
||||
JSDocTag,
|
||||
JSDocAugmentsTag,
|
||||
JSDocClassTag,
|
||||
JSDocParameterTag,
|
||||
JSDocReturnTag,
|
||||
JSDocTypeTag,
|
||||
@@ -2132,6 +2133,10 @@ namespace ts {
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
export interface JSDocClassTag extends JSDocTag {
|
||||
kind: SyntaxKind.JSDocClassTag;
|
||||
}
|
||||
|
||||
export interface JSDocTemplateTag extends JSDocTag {
|
||||
kind: SyntaxKind.JSDocTemplateTag;
|
||||
typeParameters: NodeArray<TypeParameterDeclaration>;
|
||||
|
||||
@@ -1562,6 +1562,10 @@ namespace ts {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag;
|
||||
}
|
||||
|
||||
export function getJSDocClassTag(node: Node): JSDocClassTag {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocClassTag) as JSDocClassTag;
|
||||
}
|
||||
|
||||
export function getJSDocReturnTag(node: Node): JSDocReturnTag {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user