mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix inference for generic-typed constructor parameter when no explicit constructor is present (#47750)
* assume signature is from constructor if declaration is undefined * add tests and baselines
This commit is contained in:
parent
67172e41c2
commit
1e60c8702c
@ -13077,8 +13077,11 @@ namespace ts {
|
||||
// object type literal or interface (using the new keyword). Each way of declaring a constructor
|
||||
// will result in a different declaration kind.
|
||||
if (!signature.isolatedSignatureType) {
|
||||
const kind = signature.declaration ? signature.declaration.kind : SyntaxKind.Unknown;
|
||||
const isConstructor = kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType;
|
||||
const kind = signature.declaration?.kind;
|
||||
|
||||
// If declaration is undefined, it is likely to be the signature of the default constructor.
|
||||
const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType;
|
||||
|
||||
const type = createObjectType(ObjectFlags.Anonymous);
|
||||
type.members = emptySymbols;
|
||||
type.properties = emptyArray;
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
//// [inferringReturnTypeFromConstructSignatureGeneric.ts]
|
||||
class GenericObject<T extends {} = {}> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
class GenericNumber<T extends number> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
class GenericNumberOrString<T extends number | string> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function g<T>(type: new () => T): T {
|
||||
return new type();
|
||||
}
|
||||
|
||||
const g1 = g(GenericObject);
|
||||
g1.give({});
|
||||
|
||||
const g2 = g(GenericNumber);
|
||||
g2.give(1);
|
||||
|
||||
const g3 = g(GenericNumberOrString);
|
||||
g3.give(1);
|
||||
g3.give('1');
|
||||
|
||||
//// [inferringReturnTypeFromConstructSignatureGeneric.js]
|
||||
var GenericObject = /** @class */ (function () {
|
||||
function GenericObject() {
|
||||
}
|
||||
GenericObject.prototype.give = function (value) {
|
||||
return value;
|
||||
};
|
||||
return GenericObject;
|
||||
}());
|
||||
var GenericNumber = /** @class */ (function () {
|
||||
function GenericNumber() {
|
||||
}
|
||||
GenericNumber.prototype.give = function (value) {
|
||||
return value;
|
||||
};
|
||||
return GenericNumber;
|
||||
}());
|
||||
var GenericNumberOrString = /** @class */ (function () {
|
||||
function GenericNumberOrString() {
|
||||
}
|
||||
GenericNumberOrString.prototype.give = function (value) {
|
||||
return value;
|
||||
};
|
||||
return GenericNumberOrString;
|
||||
}());
|
||||
function g(type) {
|
||||
return new type();
|
||||
}
|
||||
var g1 = g(GenericObject);
|
||||
g1.give({});
|
||||
var g2 = g(GenericNumber);
|
||||
g2.give(1);
|
||||
var g3 = g(GenericNumberOrString);
|
||||
g3.give(1);
|
||||
g3.give('1');
|
||||
@ -0,0 +1,87 @@
|
||||
=== tests/cases/compiler/inferringReturnTypeFromConstructSignatureGeneric.ts ===
|
||||
class GenericObject<T extends {} = {}> {
|
||||
>GenericObject : Symbol(GenericObject, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 20))
|
||||
|
||||
give(value: T) {
|
||||
>give : Symbol(GenericObject.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 40))
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 1, 7))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 20))
|
||||
|
||||
return value;
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 1, 7))
|
||||
}
|
||||
}
|
||||
class GenericNumber<T extends number> {
|
||||
>GenericNumber : Symbol(GenericNumber, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 5, 20))
|
||||
|
||||
give(value: T) {
|
||||
>give : Symbol(GenericNumber.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 5, 39))
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 6, 7))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 5, 20))
|
||||
|
||||
return value;
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 6, 7))
|
||||
}
|
||||
}
|
||||
class GenericNumberOrString<T extends number | string> {
|
||||
>GenericNumberOrString : Symbol(GenericNumberOrString, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 9, 1))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 28))
|
||||
|
||||
give(value: T) {
|
||||
>give : Symbol(GenericNumberOrString.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 56))
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 11, 7))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 28))
|
||||
|
||||
return value;
|
||||
>value : Symbol(value, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 11, 7))
|
||||
}
|
||||
}
|
||||
|
||||
function g<T>(type: new () => T): T {
|
||||
>g : Symbol(g, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 14, 1))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 16, 11))
|
||||
>type : Symbol(type, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 16, 14))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 16, 11))
|
||||
>T : Symbol(T, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 16, 11))
|
||||
|
||||
return new type();
|
||||
>type : Symbol(type, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 16, 14))
|
||||
}
|
||||
|
||||
const g1 = g(GenericObject);
|
||||
>g1 : Symbol(g1, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 20, 5))
|
||||
>g : Symbol(g, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 14, 1))
|
||||
>GenericObject : Symbol(GenericObject, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 0))
|
||||
|
||||
g1.give({});
|
||||
>g1.give : Symbol(GenericObject.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 40))
|
||||
>g1 : Symbol(g1, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 20, 5))
|
||||
>give : Symbol(GenericObject.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 0, 40))
|
||||
|
||||
const g2 = g(GenericNumber);
|
||||
>g2 : Symbol(g2, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 23, 5))
|
||||
>g : Symbol(g, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 14, 1))
|
||||
>GenericNumber : Symbol(GenericNumber, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 4, 1))
|
||||
|
||||
g2.give(1);
|
||||
>g2.give : Symbol(GenericNumber.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 5, 39))
|
||||
>g2 : Symbol(g2, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 23, 5))
|
||||
>give : Symbol(GenericNumber.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 5, 39))
|
||||
|
||||
const g3 = g(GenericNumberOrString);
|
||||
>g3 : Symbol(g3, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 26, 5))
|
||||
>g : Symbol(g, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 14, 1))
|
||||
>GenericNumberOrString : Symbol(GenericNumberOrString, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 9, 1))
|
||||
|
||||
g3.give(1);
|
||||
>g3.give : Symbol(GenericNumberOrString.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 56))
|
||||
>g3 : Symbol(g3, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 26, 5))
|
||||
>give : Symbol(GenericNumberOrString.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 56))
|
||||
|
||||
g3.give('1');
|
||||
>g3.give : Symbol(GenericNumberOrString.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 56))
|
||||
>g3 : Symbol(g3, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 26, 5))
|
||||
>give : Symbol(GenericNumberOrString.give, Decl(inferringReturnTypeFromConstructSignatureGeneric.ts, 10, 56))
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
=== tests/cases/compiler/inferringReturnTypeFromConstructSignatureGeneric.ts ===
|
||||
class GenericObject<T extends {} = {}> {
|
||||
>GenericObject : GenericObject<T>
|
||||
|
||||
give(value: T) {
|
||||
>give : (value: T) => T
|
||||
>value : T
|
||||
|
||||
return value;
|
||||
>value : T
|
||||
}
|
||||
}
|
||||
class GenericNumber<T extends number> {
|
||||
>GenericNumber : GenericNumber<T>
|
||||
|
||||
give(value: T) {
|
||||
>give : (value: T) => T
|
||||
>value : T
|
||||
|
||||
return value;
|
||||
>value : T
|
||||
}
|
||||
}
|
||||
class GenericNumberOrString<T extends number | string> {
|
||||
>GenericNumberOrString : GenericNumberOrString<T>
|
||||
|
||||
give(value: T) {
|
||||
>give : (value: T) => T
|
||||
>value : T
|
||||
|
||||
return value;
|
||||
>value : T
|
||||
}
|
||||
}
|
||||
|
||||
function g<T>(type: new () => T): T {
|
||||
>g : <T>(type: new () => T) => T
|
||||
>type : new () => T
|
||||
|
||||
return new type();
|
||||
>new type() : T
|
||||
>type : new () => T
|
||||
}
|
||||
|
||||
const g1 = g(GenericObject);
|
||||
>g1 : GenericObject<{}>
|
||||
>g(GenericObject) : GenericObject<{}>
|
||||
>g : <T>(type: new () => T) => T
|
||||
>GenericObject : typeof GenericObject
|
||||
|
||||
g1.give({});
|
||||
>g1.give({}) : {}
|
||||
>g1.give : (value: {}) => {}
|
||||
>g1 : GenericObject<{}>
|
||||
>give : (value: {}) => {}
|
||||
>{} : {}
|
||||
|
||||
const g2 = g(GenericNumber);
|
||||
>g2 : GenericNumber<number>
|
||||
>g(GenericNumber) : GenericNumber<number>
|
||||
>g : <T>(type: new () => T) => T
|
||||
>GenericNumber : typeof GenericNumber
|
||||
|
||||
g2.give(1);
|
||||
>g2.give(1) : number
|
||||
>g2.give : (value: number) => number
|
||||
>g2 : GenericNumber<number>
|
||||
>give : (value: number) => number
|
||||
>1 : 1
|
||||
|
||||
const g3 = g(GenericNumberOrString);
|
||||
>g3 : GenericNumberOrString<string | number>
|
||||
>g(GenericNumberOrString) : GenericNumberOrString<string | number>
|
||||
>g : <T>(type: new () => T) => T
|
||||
>GenericNumberOrString : typeof GenericNumberOrString
|
||||
|
||||
g3.give(1);
|
||||
>g3.give(1) : string | number
|
||||
>g3.give : (value: string | number) => string | number
|
||||
>g3 : GenericNumberOrString<string | number>
|
||||
>give : (value: string | number) => string | number
|
||||
>1 : 1
|
||||
|
||||
g3.give('1');
|
||||
>g3.give('1') : string | number
|
||||
>g3.give : (value: string | number) => string | number
|
||||
>g3 : GenericNumberOrString<string | number>
|
||||
>give : (value: string | number) => string | number
|
||||
>'1' : "1"
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
class GenericObject<T extends {} = {}> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
class GenericNumber<T extends number> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
class GenericNumberOrString<T extends number | string> {
|
||||
give(value: T) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function g<T>(type: new () => T): T {
|
||||
return new type();
|
||||
}
|
||||
|
||||
const g1 = g(GenericObject);
|
||||
g1.give({});
|
||||
|
||||
const g2 = g(GenericNumber);
|
||||
g2.give(1);
|
||||
|
||||
const g3 = g(GenericNumberOrString);
|
||||
g3.give(1);
|
||||
g3.give('1');
|
||||
Loading…
x
Reference in New Issue
Block a user