diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 438e46eca11b6..acdbcab6b0ef3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21374,6 +21374,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return Ternary.True; } + const sourceIsAbstract = !!(source.flags & SignatureFlags.Abstract); + const targetIsAbstract = !!(target.flags & SignatureFlags.Abstract); + + // An abstract constructor type is not assignable to a non-abstract constructor type + // as it would otherwise be possible to new an abstract class. Note that the assignability + // check we perform for an extends clause excludes construct signatures from the target, + // so this check never proceeds. + if (sourceIsAbstract && !targetIsAbstract) { + if (reportErrors) { + errorReporter!(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return Ternary.False; + } + if (!(checkMode & SignatureCheckMode.StrictTopSignature && isTopSignature(source)) && isTopSignature(target)) { return Ternary.True; } @@ -24044,18 +24058,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) { - const sourceIsAbstract = !!(sourceSignatures[0].flags & SignatureFlags.Abstract); - const targetIsAbstract = !!(targetSignatures[0].flags & SignatureFlags.Abstract); - if (sourceIsAbstract && !targetIsAbstract) { - // An abstract constructor type is not assignable to a non-abstract constructor type - // as it would otherwise be possible to new an abstract class. Note that the assignability - // check we perform for an extends clause excludes construct signatures from the target, - // so this check never proceeds. - if (reportErrors) { - reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); - } - return Ternary.False; - } if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) { return Ternary.False; } @@ -36429,17 +36431,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // then it cannot be instantiated. // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. - if (someSignature(constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract))) { + const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); + if (valueDecl && hasSyntacticModifier(valueDecl, ModifierFlags.Abstract)) { error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && hasSyntacticModifier(valueDecl, ModifierFlags.Abstract)) { + + const resolvedSignature = resolveCall(node, constructSignatures, candidatesOutArray, checkMode, SignatureFlags.None); + + // Composite signature check is done to prevent instantiating unions of mixed concrete/asbtract signatures. + if ( + (resolvedSignature.flags & SignatureFlags.Abstract) + || (resolvedSignature.compositeSignatures?.some(signature => signature.flags & SignatureFlags.Abstract)) + ) { error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, checkMode, SignatureFlags.None); + return resolvedSignature; } // If expressionType's apparent type is an object type with no construct signatures but @@ -36464,13 +36473,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveErrorCall(node); } - function someSignature(signatures: Signature | readonly Signature[], f: (s: Signature) => boolean): boolean { - if (isArray(signatures)) { - return some(signatures, signature => someSignature(signature, f)); - } - return signatures.compositeKind === TypeFlags.Union ? some(signatures.compositeSignatures, f) : f(signatures); - } - function typeHasProtectedAccessibleBase(target: Symbol, type: InterfaceType): boolean { const baseTypes = getBaseTypes(type); if (!length(baseTypes)) { diff --git a/tests/baselines/reference/abstractConstructorAssignability.errors.txt b/tests/baselines/reference/abstractConstructorAssignability.errors.txt new file mode 100644 index 0000000000000..3d1c389c55540 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorAssignability.errors.txt @@ -0,0 +1,31 @@ +abstractConstructorAssignability.ts(7,1): error TS2322: Type 'AbstractConstructor' is not assignable to type 'ConcreteConstructor'. + Cannot assign an abstract constructor type to a non-abstract constructor type. +abstractConstructorAssignability.ts(16,1): error TS2322: Type 'typeof AbstractClass' is not assignable to type 'typeof ConcreteClass'. + Cannot assign an abstract constructor type to a non-abstract constructor type. + + +==== abstractConstructorAssignability.ts (2 errors) ==== + type ConcreteConstructor = new () => void; + type AbstractConstructor = abstract new () => void; + + declare let concreteConstructor: ConcreteConstructor; + declare let abstractConstructor: AbstractConstructor; + + concreteConstructor = abstractConstructor; // should error + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'AbstractConstructor' is not assignable to type 'ConcreteConstructor'. +!!! error TS2322: Cannot assign an abstract constructor type to a non-abstract constructor type. + abstractConstructor = concreteConstructor; // should work + + class ConcreteClass {} + abstract class AbstractClass {} + + declare let concreteClass: typeof ConcreteClass + declare let abstractClass: typeof AbstractClass + + concreteClass = abstractClass; // should error + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'typeof AbstractClass' is not assignable to type 'typeof ConcreteClass'. +!!! error TS2322: Cannot assign an abstract constructor type to a non-abstract constructor type. + abstractClass = concreteClass; // should work + \ No newline at end of file diff --git a/tests/baselines/reference/abstractConstructorAssignability.js b/tests/baselines/reference/abstractConstructorAssignability.js new file mode 100644 index 0000000000000..8329b18ee0ebc --- /dev/null +++ b/tests/baselines/reference/abstractConstructorAssignability.js @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/abstractConstructorAssignability.ts] //// + +//// [abstractConstructorAssignability.ts] +type ConcreteConstructor = new () => void; +type AbstractConstructor = abstract new () => void; + +declare let concreteConstructor: ConcreteConstructor; +declare let abstractConstructor: AbstractConstructor; + +concreteConstructor = abstractConstructor; // should error +abstractConstructor = concreteConstructor; // should work + +class ConcreteClass {} +abstract class AbstractClass {} + +declare let concreteClass: typeof ConcreteClass +declare let abstractClass: typeof AbstractClass + +concreteClass = abstractClass; // should error +abstractClass = concreteClass; // should work + + +//// [abstractConstructorAssignability.js] +concreteConstructor = abstractConstructor; // should error +abstractConstructor = concreteConstructor; // should work +var ConcreteClass = /** @class */ (function () { + function ConcreteClass() { + } + return ConcreteClass; +}()); +var AbstractClass = /** @class */ (function () { + function AbstractClass() { + } + return AbstractClass; +}()); +concreteClass = abstractClass; // should error +abstractClass = concreteClass; // should work diff --git a/tests/baselines/reference/abstractConstructorAssignability.symbols b/tests/baselines/reference/abstractConstructorAssignability.symbols new file mode 100644 index 0000000000000..efda8391e8c92 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorAssignability.symbols @@ -0,0 +1,47 @@ +//// [tests/cases/compiler/abstractConstructorAssignability.ts] //// + +=== abstractConstructorAssignability.ts === +type ConcreteConstructor = new () => void; +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorAssignability.ts, 0, 0)) + +type AbstractConstructor = abstract new () => void; +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorAssignability.ts, 0, 42)) + +declare let concreteConstructor: ConcreteConstructor; +>concreteConstructor : Symbol(concreteConstructor, Decl(abstractConstructorAssignability.ts, 3, 11)) +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorAssignability.ts, 0, 0)) + +declare let abstractConstructor: AbstractConstructor; +>abstractConstructor : Symbol(abstractConstructor, Decl(abstractConstructorAssignability.ts, 4, 11)) +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorAssignability.ts, 0, 42)) + +concreteConstructor = abstractConstructor; // should error +>concreteConstructor : Symbol(concreteConstructor, Decl(abstractConstructorAssignability.ts, 3, 11)) +>abstractConstructor : Symbol(abstractConstructor, Decl(abstractConstructorAssignability.ts, 4, 11)) + +abstractConstructor = concreteConstructor; // should work +>abstractConstructor : Symbol(abstractConstructor, Decl(abstractConstructorAssignability.ts, 4, 11)) +>concreteConstructor : Symbol(concreteConstructor, Decl(abstractConstructorAssignability.ts, 3, 11)) + +class ConcreteClass {} +>ConcreteClass : Symbol(ConcreteClass, Decl(abstractConstructorAssignability.ts, 7, 42)) + +abstract class AbstractClass {} +>AbstractClass : Symbol(AbstractClass, Decl(abstractConstructorAssignability.ts, 9, 22)) + +declare let concreteClass: typeof ConcreteClass +>concreteClass : Symbol(concreteClass, Decl(abstractConstructorAssignability.ts, 12, 11)) +>ConcreteClass : Symbol(ConcreteClass, Decl(abstractConstructorAssignability.ts, 7, 42)) + +declare let abstractClass: typeof AbstractClass +>abstractClass : Symbol(abstractClass, Decl(abstractConstructorAssignability.ts, 13, 11)) +>AbstractClass : Symbol(AbstractClass, Decl(abstractConstructorAssignability.ts, 9, 22)) + +concreteClass = abstractClass; // should error +>concreteClass : Symbol(concreteClass, Decl(abstractConstructorAssignability.ts, 12, 11)) +>abstractClass : Symbol(abstractClass, Decl(abstractConstructorAssignability.ts, 13, 11)) + +abstractClass = concreteClass; // should work +>abstractClass : Symbol(abstractClass, Decl(abstractConstructorAssignability.ts, 13, 11)) +>concreteClass : Symbol(concreteClass, Decl(abstractConstructorAssignability.ts, 12, 11)) + diff --git a/tests/baselines/reference/abstractConstructorAssignability.types b/tests/baselines/reference/abstractConstructorAssignability.types new file mode 100644 index 0000000000000..7d3bac6ac2d54 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorAssignability.types @@ -0,0 +1,71 @@ +//// [tests/cases/compiler/abstractConstructorAssignability.ts] //// + +=== abstractConstructorAssignability.ts === +type ConcreteConstructor = new () => void; +>ConcreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +type AbstractConstructor = abstract new () => void; +>AbstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +declare let concreteConstructor: ConcreteConstructor; +>concreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +declare let abstractConstructor: AbstractConstructor; +>abstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +concreteConstructor = abstractConstructor; // should error +>concreteConstructor = abstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>concreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>abstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +abstractConstructor = concreteConstructor; // should work +>abstractConstructor = concreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>abstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>concreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ + +class ConcreteClass {} +>ConcreteClass : ConcreteClass +> : ^^^^^^^^^^^^^ + +abstract class AbstractClass {} +>AbstractClass : AbstractClass +> : ^^^^^^^^^^^^^ + +declare let concreteClass: typeof ConcreteClass +>concreteClass : typeof ConcreteClass +> : ^^^^^^^^^^^^^^^^^^^^ +>ConcreteClass : typeof ConcreteClass +> : ^^^^^^^^^^^^^^^^^^^^ + +declare let abstractClass: typeof AbstractClass +>abstractClass : typeof AbstractClass +> : ^^^^^^^^^^^^^^^^^^^^ +>AbstractClass : typeof AbstractClass +> : ^^^^^^^^^^^^^^^^^^^^ + +concreteClass = abstractClass; // should error +>concreteClass = abstractClass : typeof AbstractClass +> : ^^^^^^^^^^^^^^^^^^^^ +>concreteClass : typeof ConcreteClass +> : ^^^^^^^^^^^^^^^^^^^^ +>abstractClass : typeof AbstractClass +> : ^^^^^^^^^^^^^^^^^^^^ + +abstractClass = concreteClass; // should work +>abstractClass = concreteClass : typeof ConcreteClass +> : ^^^^^^^^^^^^^^^^^^^^ +>abstractClass : typeof AbstractClass +> : ^^^^^^^^^^^^^^^^^^^^ +>concreteClass : typeof ConcreteClass +> : ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/abstractConstructorOverloadAssignability.js b/tests/baselines/reference/abstractConstructorOverloadAssignability.js new file mode 100644 index 0000000000000..870861f1926b4 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadAssignability.js @@ -0,0 +1,60 @@ +//// [tests/cases/compiler/abstractConstructorOverloadAssignability.ts] //// + +//// [abstractConstructorOverloadAssignability.ts] +type AbstractConstructor = abstract new (arg: "abstract") => "abstract"; +type ConcreteConstructor = new (arg: "concrete") => "concrete"; + +type MixedConstructorAbstractFirst = + & AbstractConstructor + & ConcreteConstructor; + +type MixedConstructorAbstractLast = + & ConcreteConstructor + & AbstractConstructor; + +declare let mixedConstructorAbstractFirst: MixedConstructorAbstractFirst; +declare let mixedConstructorAbstractLast: MixedConstructorAbstractLast; + +mixedConstructorAbstractFirst = mixedConstructorAbstractLast; // should work +mixedConstructorAbstractLast = mixedConstructorAbstractFirst; // should work + +interface MixedConstructorInterface1 extends AbstractConstructor { // should work + new (arg: "concrete"): "concrete"; +} + +interface MixedConstructorInterface2 extends AbstractConstructor, ConcreteConstructor { // should work + +} + +declare let mixedConstructorInterface1: MixedConstructorInterface1; +declare let mixedConstructorInterface2: MixedConstructorInterface2; + +mixedConstructorInterface2 = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorInterface2; // should work + +mixedConstructorAbstractFirst = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractFirst; // should work + +mixedConstructorAbstractLast = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractLast; // should work + +mixedConstructorAbstractFirst = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractFirst; // should work + +mixedConstructorAbstractLast = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractLast; // should work + + +//// [abstractConstructorOverloadAssignability.js] +mixedConstructorAbstractFirst = mixedConstructorAbstractLast; // should work +mixedConstructorAbstractLast = mixedConstructorAbstractFirst; // should work +mixedConstructorInterface2 = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorInterface2; // should work +mixedConstructorAbstractFirst = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractFirst; // should work +mixedConstructorAbstractLast = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractLast; // should work +mixedConstructorAbstractFirst = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractFirst; // should work +mixedConstructorAbstractLast = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractLast; // should work diff --git a/tests/baselines/reference/abstractConstructorOverloadAssignability.symbols b/tests/baselines/reference/abstractConstructorOverloadAssignability.symbols new file mode 100644 index 0000000000000..0e472d0080459 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadAssignability.symbols @@ -0,0 +1,108 @@ +//// [tests/cases/compiler/abstractConstructorOverloadAssignability.ts] //// + +=== abstractConstructorOverloadAssignability.ts === +type AbstractConstructor = abstract new (arg: "abstract") => "abstract"; +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 0)) +>arg : Symbol(arg, Decl(abstractConstructorOverloadAssignability.ts, 0, 41)) + +type ConcreteConstructor = new (arg: "concrete") => "concrete"; +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 72)) +>arg : Symbol(arg, Decl(abstractConstructorOverloadAssignability.ts, 1, 32)) + +type MixedConstructorAbstractFirst = +>MixedConstructorAbstractFirst : Symbol(MixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 1, 63)) + + & AbstractConstructor +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 0)) + + & ConcreteConstructor; +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 72)) + +type MixedConstructorAbstractLast = +>MixedConstructorAbstractLast : Symbol(MixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 5, 26)) + + & ConcreteConstructor +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 72)) + + & AbstractConstructor; +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 0)) + +declare let mixedConstructorAbstractFirst: MixedConstructorAbstractFirst; +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) +>MixedConstructorAbstractFirst : Symbol(MixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 1, 63)) + +declare let mixedConstructorAbstractLast: MixedConstructorAbstractLast; +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) +>MixedConstructorAbstractLast : Symbol(MixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 5, 26)) + +mixedConstructorAbstractFirst = mixedConstructorAbstractLast; // should work +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) + +mixedConstructorAbstractLast = mixedConstructorAbstractFirst; // should work +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) + +interface MixedConstructorInterface1 extends AbstractConstructor { // should work +>MixedConstructorInterface1 : Symbol(MixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 15, 61)) +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 0)) + + new (arg: "concrete"): "concrete"; +>arg : Symbol(arg, Decl(abstractConstructorOverloadAssignability.ts, 18, 9)) +} + +interface MixedConstructorInterface2 extends AbstractConstructor, ConcreteConstructor { // should work +>MixedConstructorInterface2 : Symbol(MixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 19, 1)) +>AbstractConstructor : Symbol(AbstractConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 0)) +>ConcreteConstructor : Symbol(ConcreteConstructor, Decl(abstractConstructorOverloadAssignability.ts, 0, 72)) + +} + +declare let mixedConstructorInterface1: MixedConstructorInterface1; +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) +>MixedConstructorInterface1 : Symbol(MixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 15, 61)) + +declare let mixedConstructorInterface2: MixedConstructorInterface2; +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) +>MixedConstructorInterface2 : Symbol(MixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 19, 1)) + +mixedConstructorInterface2 = mixedConstructorInterface1; // should work +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) + +mixedConstructorInterface1 = mixedConstructorInterface2; // should work +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) + +mixedConstructorAbstractFirst = mixedConstructorInterface1; // should work +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) + +mixedConstructorInterface1 = mixedConstructorAbstractFirst; // should work +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) + +mixedConstructorAbstractLast = mixedConstructorInterface1; // should work +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) + +mixedConstructorInterface1 = mixedConstructorAbstractLast; // should work +>mixedConstructorInterface1 : Symbol(mixedConstructorInterface1, Decl(abstractConstructorOverloadAssignability.ts, 25, 11)) +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) + +mixedConstructorAbstractFirst = mixedConstructorInterface2; // should work +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) + +mixedConstructorInterface2 = mixedConstructorAbstractFirst; // should work +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) +>mixedConstructorAbstractFirst : Symbol(mixedConstructorAbstractFirst, Decl(abstractConstructorOverloadAssignability.ts, 11, 11)) + +mixedConstructorAbstractLast = mixedConstructorInterface2; // should work +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) + +mixedConstructorInterface2 = mixedConstructorAbstractLast; // should work +>mixedConstructorInterface2 : Symbol(mixedConstructorInterface2, Decl(abstractConstructorOverloadAssignability.ts, 26, 11)) +>mixedConstructorAbstractLast : Symbol(mixedConstructorAbstractLast, Decl(abstractConstructorOverloadAssignability.ts, 12, 11)) + diff --git a/tests/baselines/reference/abstractConstructorOverloadAssignability.types b/tests/baselines/reference/abstractConstructorOverloadAssignability.types new file mode 100644 index 0000000000000..3af5de750855c --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadAssignability.types @@ -0,0 +1,151 @@ +//// [tests/cases/compiler/abstractConstructorOverloadAssignability.ts] //// + +=== abstractConstructorOverloadAssignability.ts === +type AbstractConstructor = abstract new (arg: "abstract") => "abstract"; +>AbstractConstructor : AbstractConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>arg : "abstract" +> : ^^^^^^^^^^ + +type ConcreteConstructor = new (arg: "concrete") => "concrete"; +>ConcreteConstructor : ConcreteConstructor +> : ^^^^^^^^^^^^^^^^^^^ +>arg : "concrete" +> : ^^^^^^^^^^ + +type MixedConstructorAbstractFirst = +>MixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & AbstractConstructor + & ConcreteConstructor; + +type MixedConstructorAbstractLast = +>MixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & ConcreteConstructor + & AbstractConstructor; + +declare let mixedConstructorAbstractFirst: MixedConstructorAbstractFirst; +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare let mixedConstructorAbstractLast: MixedConstructorAbstractLast; +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractFirst = mixedConstructorAbstractLast; // should work +>mixedConstructorAbstractFirst = mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractLast = mixedConstructorAbstractFirst; // should work +>mixedConstructorAbstractLast = mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +interface MixedConstructorInterface1 extends AbstractConstructor { // should work + new (arg: "concrete"): "concrete"; +>arg : "concrete" +> : ^^^^^^^^^^ +} + +interface MixedConstructorInterface2 extends AbstractConstructor, ConcreteConstructor { // should work + +} + +declare let mixedConstructorInterface1: MixedConstructorInterface1; +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare let mixedConstructorInterface2: MixedConstructorInterface2; +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface2 = mixedConstructorInterface1; // should work +>mixedConstructorInterface2 = mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface1 = mixedConstructorInterface2; // should work +>mixedConstructorInterface1 = mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractFirst = mixedConstructorInterface1; // should work +>mixedConstructorAbstractFirst = mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface1 = mixedConstructorAbstractFirst; // should work +>mixedConstructorInterface1 = mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractLast = mixedConstructorInterface1; // should work +>mixedConstructorAbstractLast = mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface1 = mixedConstructorAbstractLast; // should work +>mixedConstructorInterface1 = mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface1 : MixedConstructorInterface1 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractFirst = mixedConstructorInterface2; // should work +>mixedConstructorAbstractFirst = mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface2 = mixedConstructorAbstractFirst; // should work +>mixedConstructorInterface2 = mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractFirst : MixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorAbstractLast = mixedConstructorInterface2; // should work +>mixedConstructorAbstractLast = mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +mixedConstructorInterface2 = mixedConstructorAbstractLast; // should work +>mixedConstructorInterface2 = mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorInterface2 : MixedConstructorInterface2 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mixedConstructorAbstractLast : MixedConstructorAbstractLast +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/baselines/reference/abstractConstructorOverloadInstantiation.errors.txt b/tests/baselines/reference/abstractConstructorOverloadInstantiation.errors.txt new file mode 100644 index 0000000000000..1e6293aba7365 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadInstantiation.errors.txt @@ -0,0 +1,52 @@ +abstractConstructorOverloadInstantiation.ts(5,1): error TS2511: Cannot create an instance of an abstract class. +abstractConstructorOverloadInstantiation.ts(18,1): error TS2511: Cannot create an instance of an abstract class. +abstractConstructorOverloadInstantiation.ts(32,1): error TS2511: Cannot create an instance of an abstract class. +abstractConstructorOverloadInstantiation.ts(35,1): error TS2511: Cannot create an instance of an abstract class. + + +==== abstractConstructorOverloadInstantiation.ts (4 errors) ==== + declare const concreteConstructor: new () => void; + declare const abstractConstructor: abstract new () => void; + + new concreteConstructor(); // should work + new abstractConstructor(); // should error + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + + type AmbiguousMixedConstructorAbstractFirst = + & (abstract new () => void) + & (new () => void); + + type AmbiguousMixedConstructorConcreteFirst = + & (new () => void) + & (abstract new () => void); + + declare const ambiguousMixedConstructorAbstractFirst: AmbiguousMixedConstructorAbstractFirst; + declare const ambiguousMixedConstructorConcreteFirst: AmbiguousMixedConstructorConcreteFirst; + + new ambiguousMixedConstructorAbstractFirst(); // should error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + new ambiguousMixedConstructorConcreteFirst(); // should work + + type DistinctMixedConstructorAbstractFirst = + & (abstract new (arg: "abstract") => void) + & (new (arg: "concrete") => void); + + type DistinctMixedConstructorConcreteFirst = + & (new (arg: "concrete") => void) + & (abstract new (arg: "abstract") => void); + + declare let distinctMixedConstructorAbstractFirst: DistinctMixedConstructorAbstractFirst; + declare let distinctMixedConstructorConcreteFirst: DistinctMixedConstructorConcreteFirst; + + new distinctMixedConstructorAbstractFirst("abstract"); // should error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + new distinctMixedConstructorAbstractFirst("concrete"); // should work + + new distinctMixedConstructorConcreteFirst("abstract"); // should error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + new distinctMixedConstructorConcreteFirst("concrete"); // should work + \ No newline at end of file diff --git a/tests/baselines/reference/abstractConstructorOverloadInstantiation.js b/tests/baselines/reference/abstractConstructorOverloadInstantiation.js new file mode 100644 index 0000000000000..96878949693d2 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadInstantiation.js @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/abstractConstructorOverloadInstantiation.ts] //// + +//// [abstractConstructorOverloadInstantiation.ts] +declare const concreteConstructor: new () => void; +declare const abstractConstructor: abstract new () => void; + +new concreteConstructor(); // should work +new abstractConstructor(); // should error + +type AmbiguousMixedConstructorAbstractFirst = + & (abstract new () => void) + & (new () => void); + +type AmbiguousMixedConstructorConcreteFirst = + & (new () => void) + & (abstract new () => void); + +declare const ambiguousMixedConstructorAbstractFirst: AmbiguousMixedConstructorAbstractFirst; +declare const ambiguousMixedConstructorConcreteFirst: AmbiguousMixedConstructorConcreteFirst; + +new ambiguousMixedConstructorAbstractFirst(); // should error +new ambiguousMixedConstructorConcreteFirst(); // should work + +type DistinctMixedConstructorAbstractFirst = + & (abstract new (arg: "abstract") => void) + & (new (arg: "concrete") => void); + +type DistinctMixedConstructorConcreteFirst = + & (new (arg: "concrete") => void) + & (abstract new (arg: "abstract") => void); + +declare let distinctMixedConstructorAbstractFirst: DistinctMixedConstructorAbstractFirst; +declare let distinctMixedConstructorConcreteFirst: DistinctMixedConstructorConcreteFirst; + +new distinctMixedConstructorAbstractFirst("abstract"); // should error +new distinctMixedConstructorAbstractFirst("concrete"); // should work + +new distinctMixedConstructorConcreteFirst("abstract"); // should error +new distinctMixedConstructorConcreteFirst("concrete"); // should work + + +//// [abstractConstructorOverloadInstantiation.js] +new concreteConstructor(); // should work +new abstractConstructor(); // should error +new ambiguousMixedConstructorAbstractFirst(); // should error +new ambiguousMixedConstructorConcreteFirst(); // should work +new distinctMixedConstructorAbstractFirst("abstract"); // should error +new distinctMixedConstructorAbstractFirst("concrete"); // should work +new distinctMixedConstructorConcreteFirst("abstract"); // should error +new distinctMixedConstructorConcreteFirst("concrete"); // should work diff --git a/tests/baselines/reference/abstractConstructorOverloadInstantiation.symbols b/tests/baselines/reference/abstractConstructorOverloadInstantiation.symbols new file mode 100644 index 0000000000000..03a14396a3d75 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadInstantiation.symbols @@ -0,0 +1,79 @@ +//// [tests/cases/compiler/abstractConstructorOverloadInstantiation.ts] //// + +=== abstractConstructorOverloadInstantiation.ts === +declare const concreteConstructor: new () => void; +>concreteConstructor : Symbol(concreteConstructor, Decl(abstractConstructorOverloadInstantiation.ts, 0, 13)) + +declare const abstractConstructor: abstract new () => void; +>abstractConstructor : Symbol(abstractConstructor, Decl(abstractConstructorOverloadInstantiation.ts, 1, 13)) + +new concreteConstructor(); // should work +>concreteConstructor : Symbol(concreteConstructor, Decl(abstractConstructorOverloadInstantiation.ts, 0, 13)) + +new abstractConstructor(); // should error +>abstractConstructor : Symbol(abstractConstructor, Decl(abstractConstructorOverloadInstantiation.ts, 1, 13)) + +type AmbiguousMixedConstructorAbstractFirst = +>AmbiguousMixedConstructorAbstractFirst : Symbol(AmbiguousMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 4, 26)) + + & (abstract new () => void) + & (new () => void); + +type AmbiguousMixedConstructorConcreteFirst = +>AmbiguousMixedConstructorConcreteFirst : Symbol(AmbiguousMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 8, 23)) + + & (new () => void) + & (abstract new () => void); + +declare const ambiguousMixedConstructorAbstractFirst: AmbiguousMixedConstructorAbstractFirst; +>ambiguousMixedConstructorAbstractFirst : Symbol(ambiguousMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 14, 13)) +>AmbiguousMixedConstructorAbstractFirst : Symbol(AmbiguousMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 4, 26)) + +declare const ambiguousMixedConstructorConcreteFirst: AmbiguousMixedConstructorConcreteFirst; +>ambiguousMixedConstructorConcreteFirst : Symbol(ambiguousMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 15, 13)) +>AmbiguousMixedConstructorConcreteFirst : Symbol(AmbiguousMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 8, 23)) + +new ambiguousMixedConstructorAbstractFirst(); // should error +>ambiguousMixedConstructorAbstractFirst : Symbol(ambiguousMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 14, 13)) + +new ambiguousMixedConstructorConcreteFirst(); // should work +>ambiguousMixedConstructorConcreteFirst : Symbol(ambiguousMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 15, 13)) + +type DistinctMixedConstructorAbstractFirst = +>DistinctMixedConstructorAbstractFirst : Symbol(DistinctMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 18, 45)) + + & (abstract new (arg: "abstract") => void) +>arg : Symbol(arg, Decl(abstractConstructorOverloadInstantiation.ts, 21, 21)) + + & (new (arg: "concrete") => void); +>arg : Symbol(arg, Decl(abstractConstructorOverloadInstantiation.ts, 22, 12)) + +type DistinctMixedConstructorConcreteFirst = +>DistinctMixedConstructorConcreteFirst : Symbol(DistinctMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 22, 38)) + + & (new (arg: "concrete") => void) +>arg : Symbol(arg, Decl(abstractConstructorOverloadInstantiation.ts, 25, 12)) + + & (abstract new (arg: "abstract") => void); +>arg : Symbol(arg, Decl(abstractConstructorOverloadInstantiation.ts, 26, 21)) + +declare let distinctMixedConstructorAbstractFirst: DistinctMixedConstructorAbstractFirst; +>distinctMixedConstructorAbstractFirst : Symbol(distinctMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 28, 11)) +>DistinctMixedConstructorAbstractFirst : Symbol(DistinctMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 18, 45)) + +declare let distinctMixedConstructorConcreteFirst: DistinctMixedConstructorConcreteFirst; +>distinctMixedConstructorConcreteFirst : Symbol(distinctMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 29, 11)) +>DistinctMixedConstructorConcreteFirst : Symbol(DistinctMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 22, 38)) + +new distinctMixedConstructorAbstractFirst("abstract"); // should error +>distinctMixedConstructorAbstractFirst : Symbol(distinctMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 28, 11)) + +new distinctMixedConstructorAbstractFirst("concrete"); // should work +>distinctMixedConstructorAbstractFirst : Symbol(distinctMixedConstructorAbstractFirst, Decl(abstractConstructorOverloadInstantiation.ts, 28, 11)) + +new distinctMixedConstructorConcreteFirst("abstract"); // should error +>distinctMixedConstructorConcreteFirst : Symbol(distinctMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 29, 11)) + +new distinctMixedConstructorConcreteFirst("concrete"); // should work +>distinctMixedConstructorConcreteFirst : Symbol(distinctMixedConstructorConcreteFirst, Decl(abstractConstructorOverloadInstantiation.ts, 29, 11)) + diff --git a/tests/baselines/reference/abstractConstructorOverloadInstantiation.types b/tests/baselines/reference/abstractConstructorOverloadInstantiation.types new file mode 100644 index 0000000000000..afd23179c8a80 --- /dev/null +++ b/tests/baselines/reference/abstractConstructorOverloadInstantiation.types @@ -0,0 +1,121 @@ +//// [tests/cases/compiler/abstractConstructorOverloadInstantiation.ts] //// + +=== abstractConstructorOverloadInstantiation.ts === +declare const concreteConstructor: new () => void; +>concreteConstructor : new () => void +> : ^^^^^^^^^^ + +declare const abstractConstructor: abstract new () => void; +>abstractConstructor : abstract new () => void +> : ^^^^^^^^^^^^^^^^^^^ + +new concreteConstructor(); // should work +>new concreteConstructor() : void +> : ^^^^ +>concreteConstructor : new () => void +> : ^^^^^^^^^^ + +new abstractConstructor(); // should error +>new abstractConstructor() : any +> : ^^^ +>abstractConstructor : abstract new () => void +> : ^^^^^^^^^^^^^^^^^^^ + +type AmbiguousMixedConstructorAbstractFirst = +>AmbiguousMixedConstructorAbstractFirst : AmbiguousMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & (abstract new () => void) + & (new () => void); + +type AmbiguousMixedConstructorConcreteFirst = +>AmbiguousMixedConstructorConcreteFirst : AmbiguousMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & (new () => void) + & (abstract new () => void); + +declare const ambiguousMixedConstructorAbstractFirst: AmbiguousMixedConstructorAbstractFirst; +>ambiguousMixedConstructorAbstractFirst : AmbiguousMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const ambiguousMixedConstructorConcreteFirst: AmbiguousMixedConstructorConcreteFirst; +>ambiguousMixedConstructorConcreteFirst : AmbiguousMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +new ambiguousMixedConstructorAbstractFirst(); // should error +>new ambiguousMixedConstructorAbstractFirst() : any +> : ^^^ +>ambiguousMixedConstructorAbstractFirst : AmbiguousMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +new ambiguousMixedConstructorConcreteFirst(); // should work +>new ambiguousMixedConstructorConcreteFirst() : void +> : ^^^^ +>ambiguousMixedConstructorConcreteFirst : AmbiguousMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +type DistinctMixedConstructorAbstractFirst = +>DistinctMixedConstructorAbstractFirst : DistinctMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & (abstract new (arg: "abstract") => void) +>arg : "abstract" +> : ^^^^^^^^^^ + + & (new (arg: "concrete") => void); +>arg : "concrete" +> : ^^^^^^^^^^ + +type DistinctMixedConstructorConcreteFirst = +>DistinctMixedConstructorConcreteFirst : DistinctMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + & (new (arg: "concrete") => void) +>arg : "concrete" +> : ^^^^^^^^^^ + + & (abstract new (arg: "abstract") => void); +>arg : "abstract" +> : ^^^^^^^^^^ + +declare let distinctMixedConstructorAbstractFirst: DistinctMixedConstructorAbstractFirst; +>distinctMixedConstructorAbstractFirst : DistinctMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare let distinctMixedConstructorConcreteFirst: DistinctMixedConstructorConcreteFirst; +>distinctMixedConstructorConcreteFirst : DistinctMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +new distinctMixedConstructorAbstractFirst("abstract"); // should error +>new distinctMixedConstructorAbstractFirst("abstract") : any +> : ^^^ +>distinctMixedConstructorAbstractFirst : DistinctMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"abstract" : "abstract" +> : ^^^^^^^^^^ + +new distinctMixedConstructorAbstractFirst("concrete"); // should work +>new distinctMixedConstructorAbstractFirst("concrete") : void +> : ^^^^ +>distinctMixedConstructorAbstractFirst : DistinctMixedConstructorAbstractFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"concrete" : "concrete" +> : ^^^^^^^^^^ + +new distinctMixedConstructorConcreteFirst("abstract"); // should error +>new distinctMixedConstructorConcreteFirst("abstract") : any +> : ^^^ +>distinctMixedConstructorConcreteFirst : DistinctMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"abstract" : "abstract" +> : ^^^^^^^^^^ + +new distinctMixedConstructorConcreteFirst("concrete"); // should work +>new distinctMixedConstructorConcreteFirst("concrete") : void +> : ^^^^ +>distinctMixedConstructorConcreteFirst : DistinctMixedConstructorConcreteFirst +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>"concrete" : "concrete" +> : ^^^^^^^^^^ + diff --git a/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js b/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js index 448760fe05df2..c271aa5b3dbb2 100644 --- a/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js +++ b/tests/baselines/reference/tsc/declarationEmit/when-using-Windows-paths-and-uppercase-letters.js @@ -97,7 +97,9 @@ declare const console: { log(msg: any): void; }; D:\home\src\tslibs\TS\Lib\tsc.js -p D:\Work\pkg1 --explainFiles Output:: src/utils/index.ts:8:12 - error TS2352: Conversion of type 'typeof PartialClassType' to type 'MyReturnType' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. - Cannot assign an abstract constructor type to a non-abstract constructor type. + Types of construct signatures are incompatible. + Type 'abstract new () => PartialClassType' is not assignable to type 'new (...args: any[]) => any'. + Cannot assign an abstract constructor type to a non-abstract constructor type. 8 return PartialClassType as MyReturnType;    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/cases/compiler/abstractConstructorAssignability.ts b/tests/cases/compiler/abstractConstructorAssignability.ts new file mode 100644 index 0000000000000..3ac4d09a69ecf --- /dev/null +++ b/tests/cases/compiler/abstractConstructorAssignability.ts @@ -0,0 +1,17 @@ +type ConcreteConstructor = new () => void; +type AbstractConstructor = abstract new () => void; + +declare let concreteConstructor: ConcreteConstructor; +declare let abstractConstructor: AbstractConstructor; + +concreteConstructor = abstractConstructor; // should error +abstractConstructor = concreteConstructor; // should work + +class ConcreteClass {} +abstract class AbstractClass {} + +declare let concreteClass: typeof ConcreteClass +declare let abstractClass: typeof AbstractClass + +concreteClass = abstractClass; // should error +abstractClass = concreteClass; // should work diff --git a/tests/cases/compiler/abstractConstructorOverloadAssignability.ts b/tests/cases/compiler/abstractConstructorOverloadAssignability.ts new file mode 100644 index 0000000000000..9de3a947a5e39 --- /dev/null +++ b/tests/cases/compiler/abstractConstructorOverloadAssignability.ts @@ -0,0 +1,42 @@ +type AbstractConstructor = abstract new (arg: "abstract") => "abstract"; +type ConcreteConstructor = new (arg: "concrete") => "concrete"; + +type MixedConstructorAbstractFirst = + & AbstractConstructor + & ConcreteConstructor; + +type MixedConstructorAbstractLast = + & ConcreteConstructor + & AbstractConstructor; + +declare let mixedConstructorAbstractFirst: MixedConstructorAbstractFirst; +declare let mixedConstructorAbstractLast: MixedConstructorAbstractLast; + +mixedConstructorAbstractFirst = mixedConstructorAbstractLast; // should work +mixedConstructorAbstractLast = mixedConstructorAbstractFirst; // should work + +interface MixedConstructorInterface1 extends AbstractConstructor { // should work + new (arg: "concrete"): "concrete"; +} + +interface MixedConstructorInterface2 extends AbstractConstructor, ConcreteConstructor { // should work + +} + +declare let mixedConstructorInterface1: MixedConstructorInterface1; +declare let mixedConstructorInterface2: MixedConstructorInterface2; + +mixedConstructorInterface2 = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorInterface2; // should work + +mixedConstructorAbstractFirst = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractFirst; // should work + +mixedConstructorAbstractLast = mixedConstructorInterface1; // should work +mixedConstructorInterface1 = mixedConstructorAbstractLast; // should work + +mixedConstructorAbstractFirst = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractFirst; // should work + +mixedConstructorAbstractLast = mixedConstructorInterface2; // should work +mixedConstructorInterface2 = mixedConstructorAbstractLast; // should work diff --git a/tests/cases/compiler/abstractConstructorOverloadInstantiation.ts b/tests/cases/compiler/abstractConstructorOverloadInstantiation.ts new file mode 100644 index 0000000000000..ac9fb59ac228d --- /dev/null +++ b/tests/cases/compiler/abstractConstructorOverloadInstantiation.ts @@ -0,0 +1,36 @@ +declare const concreteConstructor: new () => void; +declare const abstractConstructor: abstract new () => void; + +new concreteConstructor(); // should work +new abstractConstructor(); // should error + +type AmbiguousMixedConstructorAbstractFirst = + & (abstract new () => void) + & (new () => void); + +type AmbiguousMixedConstructorConcreteFirst = + & (new () => void) + & (abstract new () => void); + +declare const ambiguousMixedConstructorAbstractFirst: AmbiguousMixedConstructorAbstractFirst; +declare const ambiguousMixedConstructorConcreteFirst: AmbiguousMixedConstructorConcreteFirst; + +new ambiguousMixedConstructorAbstractFirst(); // should error +new ambiguousMixedConstructorConcreteFirst(); // should work + +type DistinctMixedConstructorAbstractFirst = + & (abstract new (arg: "abstract") => void) + & (new (arg: "concrete") => void); + +type DistinctMixedConstructorConcreteFirst = + & (new (arg: "concrete") => void) + & (abstract new (arg: "abstract") => void); + +declare let distinctMixedConstructorAbstractFirst: DistinctMixedConstructorAbstractFirst; +declare let distinctMixedConstructorConcreteFirst: DistinctMixedConstructorConcreteFirst; + +new distinctMixedConstructorAbstractFirst("abstract"); // should error +new distinctMixedConstructorAbstractFirst("concrete"); // should work + +new distinctMixedConstructorConcreteFirst("abstract"); // should error +new distinctMixedConstructorConcreteFirst("concrete"); // should work