Fixes #26128 - signature comp for jsdoc @class. (#26160)

* Fixes #26128 - signature comp for  jsdoc @class.

Another issue caused by js functions tagged with jsdoc
`@constructor` not having construct signatures.

A jsdoc function type that constructs a type (`function(new: Ex)`),
has a construct signature and return value inferred as the
constructed type where as a jsdoc `@constructor` has no construct
signatures, and it's call signature has a void return type
(or undefined).

i.e:
```javascript
/** @constructor **/ function E() {};

// typeof E -> call signature: () => void

/** @param {function(new: E)} d */ function c(d) {}

// typeof d -> construct: () => E
```

--

This commit fixes this (in an inelegant way) by considering `@class` function signatures as construct signatures and synthesizing it's return value _only for signature comparison_.

There might be a slight performance hit, since the synthesized return value is not cached; but changing the `@class` function's return type in `getReturnTypeOfSignature` causes other issues.

* Update jsdoc function test to fix mistake.
This commit is contained in:
James Keane
2018-08-14 16:35:51 -04:00
committed by Nathan Shively-Sanders
parent cea4838972
commit a1089893bd
5 changed files with 279 additions and 4 deletions

View File

@@ -10744,11 +10744,13 @@ namespace ts {
}
if (!ignoreReturnTypes) {
const targetReturnType = getReturnTypeOfSignature(target);
const targetReturnType = (target.declaration && isJavaScriptConstructor(target.declaration)) ?
getJavaScriptClassType(target.declaration.symbol)! : getReturnTypeOfSignature(target);
if (targetReturnType === voidType) {
return result;
}
const sourceReturnType = getReturnTypeOfSignature(source);
const sourceReturnType = (source.declaration && isJavaScriptConstructor(source.declaration)) ?
getJavaScriptClassType(source.declaration.symbol)! : getReturnTypeOfSignature(source);
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
const targetTypePredicate = getTypePredicateOfSignature(target);
@@ -12015,8 +12017,14 @@ namespace ts {
return Ternary.True;
}
const sourceSignatures = getSignaturesOfType(source, kind);
const targetSignatures = getSignaturesOfType(target, kind);
const sourceIsJSConstructor = source.symbol && isJavaScriptConstructor(source.symbol.valueDeclaration);
const targetIsJSConstructor = target.symbol && isJavaScriptConstructor(target.symbol.valueDeclaration);
const sourceSignatures = getSignaturesOfType(source, (sourceIsJSConstructor && kind === SignatureKind.Construct) ?
SignatureKind.Call : kind);
const targetSignatures = getSignaturesOfType(target, (targetIsJSConstructor && kind === SignatureKind.Construct) ?
SignatureKind.Call : kind);
if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) {
if (isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
// An abstract constructor type is not assignable to a non-abstract constructor type