From 29d5e4daddc3a97ec81b338b6a3a5ae1892288fe Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Tue, 12 Sep 2017 02:21:35 +0800 Subject: [PATCH] fix #18225, fix error message on abstract class instance (#18368) * fix #18225, fix error message on abstract class instance abstract class check should be inside constructor call * add new test and accept baseline --- src/compiler/checker.ts | 20 +++++++++---------- .../reference/newAbstractInstance.errors.txt | 10 ++++++++++ .../reference/newAbstractInstance.js | 13 ++++++++++++ tests/cases/compiler/newAbstractInstance.ts | 3 +++ 4 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/newAbstractInstance.errors.txt create mode 100644 tests/baselines/reference/newAbstractInstance.js create mode 100644 tests/cases/compiler/newAbstractInstance.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff5d1c661e8..66ae64e199b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16128,16 +16128,6 @@ namespace ts { return resolveErrorCall(node); } - // If the expression is a class of abstract type, then it cannot be instantiated. - // Note, only class declarations can be declared abstract. - // In the case of a merged class-module or class-interface declaration, - // only the class declaration node will have the Abstract flag set. - const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && hasModifier(valueDecl, ModifierFlags.Abstract)) { - error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(getNameOfDeclaration(valueDecl))); - return resolveErrorCall(node); - } - // TS 1.0 spec: 4.11 // If expressionType is of type Any, Args can be any argument // list and the result of the operation is of type Any. @@ -16157,6 +16147,16 @@ namespace ts { if (!isConstructorAccessible(node, constructSignatures[0])) { return resolveErrorCall(node); } + // If the expression is a class of abstract type, then it cannot be instantiated. + // Note, only class declarations can be declared abstract. + // In the case of a merged class-module or class-interface declaration, + // only the class declaration node will have the Abstract flag set. + const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); + if (valueDecl && hasModifier(valueDecl, ModifierFlags.Abstract)) { + error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(getNameOfDeclaration(valueDecl))); + return resolveErrorCall(node); + } + return resolveCall(node, constructSignatures, candidatesOutArray); } diff --git a/tests/baselines/reference/newAbstractInstance.errors.txt b/tests/baselines/reference/newAbstractInstance.errors.txt new file mode 100644 index 00000000000..13a5aff9df3 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance.errors.txt @@ -0,0 +1,10 @@ +tests/cases/compiler/newAbstractInstance.ts(3,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + + +==== tests/cases/compiler/newAbstractInstance.ts (1 errors) ==== + abstract class B { } + declare const b: B; + new b(); + ~~~~~~~ +!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + \ No newline at end of file diff --git a/tests/baselines/reference/newAbstractInstance.js b/tests/baselines/reference/newAbstractInstance.js new file mode 100644 index 00000000000..4a84b42cc20 --- /dev/null +++ b/tests/baselines/reference/newAbstractInstance.js @@ -0,0 +1,13 @@ +//// [newAbstractInstance.ts] +abstract class B { } +declare const b: B; +new b(); + + +//// [newAbstractInstance.js] +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +new b(); diff --git a/tests/cases/compiler/newAbstractInstance.ts b/tests/cases/compiler/newAbstractInstance.ts new file mode 100644 index 00000000000..f686aafa005 --- /dev/null +++ b/tests/cases/compiler/newAbstractInstance.ts @@ -0,0 +1,3 @@ +abstract class B { } +declare const b: B; +new b();