mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 17:05:58 -05:00
Improve @overload's interactions with constructors (#52577)
This commit is contained in:
committed by
GitHub
parent
0f41b7a390
commit
0d251ba9bc
@@ -14458,7 +14458,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
for (const tag of node.tags) {
|
||||
if (isJSDocOverloadTag(tag)) {
|
||||
const jsDocSignature = tag.typeExpression;
|
||||
if (jsDocSignature.type === undefined) {
|
||||
if (jsDocSignature.type === undefined && !isConstructorDeclaration(decl)) {
|
||||
reportImplicitAny(jsDocSignature, anyType);
|
||||
}
|
||||
result.push(getSignatureFromDeclaration(jsDocSignature));
|
||||
@@ -14584,6 +14584,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (declaration.kind === SyntaxKind.Constructor) {
|
||||
return getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol));
|
||||
}
|
||||
if (isJSDocSignature(declaration)) {
|
||||
const root = getJSDocRoot(declaration);
|
||||
if (root && isConstructorDeclaration(root.parent)) {
|
||||
return getDeclaredTypeOfClassOrInterface(getMergedSymbol((root.parent.parent as ClassDeclaration).symbol));
|
||||
}
|
||||
}
|
||||
if (isJSDocConstructSignature(declaration)) {
|
||||
return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type!); // TODO: GH#18217
|
||||
}
|
||||
@@ -33773,6 +33779,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
declaration.kind !== SyntaxKind.Constructor &&
|
||||
declaration.kind !== SyntaxKind.ConstructSignature &&
|
||||
declaration.kind !== SyntaxKind.ConstructorType &&
|
||||
!(isJSDocSignature(declaration) && getJSDocRoot(declaration)?.parent?.kind === SyntaxKind.Constructor) &&
|
||||
!isJSDocConstructSignature(declaration) &&
|
||||
!isJSConstructor(declaration)) {
|
||||
|
||||
|
||||
44
tests/baselines/reference/overloadTag2.errors.txt
Normal file
44
tests/baselines/reference/overloadTag2.errors.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
tests/cases/conformance/jsdoc/overloadTag2.js(25,20): error TS7006: Parameter 'b' implicitly has an 'any' type.
|
||||
tests/cases/conformance/jsdoc/overloadTag2.js(30,9): error TS2554: Expected 1-2 arguments, but got 0.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/overloadTag2.js (2 errors) ====
|
||||
export class Foo {
|
||||
#a = true ? 1 : "1"
|
||||
#b
|
||||
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*//**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
~
|
||||
!!! error TS7006: Parameter 'b' implicitly has an 'any' type.
|
||||
this.#a = a
|
||||
this.#b = b
|
||||
}
|
||||
}
|
||||
var a = new Foo()
|
||||
~~~~~~~~~
|
||||
!!! error TS2554: Expected 1-2 arguments, but got 0.
|
||||
!!! related TS6210 tests/cases/conformance/jsdoc/overloadTag2.js:15:8: An argument for 'a' was not provided.
|
||||
var b = new Foo('str')
|
||||
var c = new Foo(2)
|
||||
var d = new Foo('str', 2)
|
||||
|
||||
78
tests/baselines/reference/overloadTag2.js
Normal file
78
tests/baselines/reference/overloadTag2.js
Normal file
@@ -0,0 +1,78 @@
|
||||
//// [overloadTag2.js]
|
||||
export class Foo {
|
||||
#a = true ? 1 : "1"
|
||||
#b
|
||||
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*//**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
this.#a = a
|
||||
this.#b = b
|
||||
}
|
||||
}
|
||||
var a = new Foo()
|
||||
var b = new Foo('str')
|
||||
var c = new Foo(2)
|
||||
var d = new Foo('str', 2)
|
||||
|
||||
|
||||
//// [overloadTag2.js]
|
||||
export class Foo {
|
||||
#a = true ? 1 : "1";
|
||||
#b;
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*/ /**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
this.#a = a;
|
||||
this.#b = b;
|
||||
}
|
||||
}
|
||||
var a = new Foo();
|
||||
var b = new Foo('str');
|
||||
var c = new Foo(2);
|
||||
var d = new Foo('str', 2);
|
||||
|
||||
|
||||
//// [overloadTag2.d.ts]
|
||||
export class Foo {
|
||||
constructor(a: string, b: number);
|
||||
constructor(a: number);
|
||||
constructor(a: string);
|
||||
#private;
|
||||
}
|
||||
61
tests/baselines/reference/overloadTag2.symbols
Normal file
61
tests/baselines/reference/overloadTag2.symbols
Normal file
@@ -0,0 +1,61 @@
|
||||
=== tests/cases/conformance/jsdoc/overloadTag2.js ===
|
||||
export class Foo {
|
||||
>Foo : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
|
||||
#a = true ? 1 : "1"
|
||||
>#a : Symbol(Foo.#a, Decl(overloadTag2.js, 0, 18))
|
||||
|
||||
#b
|
||||
>#b : Symbol(Foo.#b, Decl(overloadTag2.js, 1, 23))
|
||||
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*//**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
>a : Symbol(a, Decl(overloadTag2.js, 24, 16))
|
||||
>b : Symbol(b, Decl(overloadTag2.js, 24, 18))
|
||||
|
||||
this.#a = a
|
||||
>this.#a : Symbol(Foo.#a, Decl(overloadTag2.js, 0, 18))
|
||||
>this : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
>a : Symbol(a, Decl(overloadTag2.js, 24, 16))
|
||||
|
||||
this.#b = b
|
||||
>this.#b : Symbol(Foo.#b, Decl(overloadTag2.js, 1, 23))
|
||||
>this : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
>b : Symbol(b, Decl(overloadTag2.js, 24, 18))
|
||||
}
|
||||
}
|
||||
var a = new Foo()
|
||||
>a : Symbol(a, Decl(overloadTag2.js, 29, 3))
|
||||
>Foo : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
|
||||
var b = new Foo('str')
|
||||
>b : Symbol(b, Decl(overloadTag2.js, 30, 3))
|
||||
>Foo : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
|
||||
var c = new Foo(2)
|
||||
>c : Symbol(c, Decl(overloadTag2.js, 31, 3))
|
||||
>Foo : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
|
||||
var d = new Foo('str', 2)
|
||||
>d : Symbol(d, Decl(overloadTag2.js, 32, 3))
|
||||
>Foo : Symbol(Foo, Decl(overloadTag2.js, 0, 0))
|
||||
|
||||
75
tests/baselines/reference/overloadTag2.types
Normal file
75
tests/baselines/reference/overloadTag2.types
Normal file
@@ -0,0 +1,75 @@
|
||||
=== tests/cases/conformance/jsdoc/overloadTag2.js ===
|
||||
export class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
#a = true ? 1 : "1"
|
||||
>#a : string | number
|
||||
>true ? 1 : "1" : 1 | "1"
|
||||
>true : true
|
||||
>1 : 1
|
||||
>"1" : "1"
|
||||
|
||||
#b
|
||||
>#b : any
|
||||
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*//**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
>a : string | number
|
||||
>b : any
|
||||
|
||||
this.#a = a
|
||||
>this.#a = a : string | number
|
||||
>this.#a : string | number
|
||||
>this : this
|
||||
>a : string | number
|
||||
|
||||
this.#b = b
|
||||
>this.#b = b : any
|
||||
>this.#b : any
|
||||
>this : this
|
||||
>b : any
|
||||
}
|
||||
}
|
||||
var a = new Foo()
|
||||
>a : Foo
|
||||
>new Foo() : Foo
|
||||
>Foo : typeof Foo
|
||||
|
||||
var b = new Foo('str')
|
||||
>b : Foo
|
||||
>new Foo('str') : Foo
|
||||
>Foo : typeof Foo
|
||||
>'str' : "str"
|
||||
|
||||
var c = new Foo(2)
|
||||
>c : Foo
|
||||
>new Foo(2) : Foo
|
||||
>Foo : typeof Foo
|
||||
>2 : 2
|
||||
|
||||
var d = new Foo('str', 2)
|
||||
>d : Foo
|
||||
>new Foo('str', 2) : Foo
|
||||
>Foo : typeof Foo
|
||||
>'str' : "str"
|
||||
>2 : 2
|
||||
|
||||
40
tests/cases/conformance/jsdoc/overloadTag2.ts
Normal file
40
tests/cases/conformance/jsdoc/overloadTag2.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
// @checkJs: true
|
||||
// @allowJs: true
|
||||
// @target: esnext
|
||||
// @outdir: foo
|
||||
// @declaration: true
|
||||
// @filename: overloadTag2.js
|
||||
// @strict: true
|
||||
export class Foo {
|
||||
#a = true ? 1 : "1"
|
||||
#b
|
||||
|
||||
/**
|
||||
* Should not have an implicit any error, because constructor's return type is always implicit
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
* @param {number} b
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {number} a
|
||||
*/
|
||||
/**
|
||||
* @constructor
|
||||
* @overload
|
||||
* @param {string} a
|
||||
*//**
|
||||
* @constructor
|
||||
* @param {number | string} a
|
||||
*/
|
||||
constructor(a, b) {
|
||||
this.#a = a
|
||||
this.#b = b
|
||||
}
|
||||
}
|
||||
var a = new Foo()
|
||||
var b = new Foo('str')
|
||||
var c = new Foo(2)
|
||||
var d = new Foo('str', 2)
|
||||
Reference in New Issue
Block a user