From eb5789a0bfebcce6d37ea8a2c58ddf793e53e7c0 Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Thu, 23 Jan 2020 16:55:49 -0800
Subject: [PATCH 1/6] Add support for abstract constructor types

---
 src/compat/deprecations.ts                    |  17 +-
 src/compiler/checker.ts                       |  64 +-
 src/compiler/debug.ts                         |   9 +
 src/compiler/emitter.ts                       |   1 +
 src/compiler/factory/nodeFactory.ts           |   9 +-
 src/compiler/parser.ts                        |  27 +-
 src/compiler/transformers/declarations.ts     |   2 +-
 src/compiler/types.ts                         |  19 +-
 src/compiler/utilities.ts                     |   7 +-
 src/compiler/visitorPublic.ts                 |   1 +
 src/lib/es5.d.ts                              |   4 +-
 src/services/symbolDisplay.ts                 |   8 +
 .../reference/api/tsserverlibrary.d.ts        |   8 +-
 tests/baselines/reference/api/typescript.d.ts |   8 +-
 .../reference/inferTypes1.errors.txt          |  44 +-
 tests/baselines/reference/inferTypes1.js      |  15 +
 tests/baselines/reference/inferTypes1.symbols | 857 +++++++++---------
 tests/baselines/reference/inferTypes1.types   |  26 +
 .../mixinAbstractClasses.2.errors.txt         |  33 +
 .../reference/mixinAbstractClasses.2.js       |  55 ++
 .../reference/mixinAbstractClasses.2.symbols  |  53 ++
 .../reference/mixinAbstractClasses.2.types    |  48 +
 .../reference/mixinAbstractClasses.js         |  82 ++
 .../reference/mixinAbstractClasses.symbols    |  88 ++
 .../reference/mixinAbstractClasses.types      |  89 ++
 .../unionTypeConstructSignatures.errors.txt   |  15 +-
 .../reference/unionTypeConstructSignatures.js |  16 +-
 .../unionTypeConstructSignatures.symbols      |  12 +-
 .../unionTypeConstructSignatures.types        |  14 +-
 .../classes/mixinAbstractClasses.2.ts         |  27 +
 .../classes/mixinAbstractClasses.ts           |  37 +
 .../types/conditional/inferTypes1.ts          |   8 +
 .../union/unionTypeConstructSignatures.ts     |   9 +-
 33 files changed, 1214 insertions(+), 498 deletions(-)
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.2.errors.txt
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.2.js
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.2.symbols
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.2.types
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.js
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.symbols
 create mode 100644 tests/baselines/reference/mixinAbstractClasses.types
 create mode 100644 tests/cases/conformance/classes/mixinAbstractClasses.2.ts
 create mode 100644 tests/cases/conformance/classes/mixinAbstractClasses.ts

diff --git a/src/compat/deprecations.ts b/src/compat/deprecations.ts
index e9a6dc3b9a878..f3caab088e4b7 100644
--- a/src/compat/deprecations.ts
+++ b/src/compat/deprecations.ts
@@ -164,10 +164,23 @@ namespace ts {
     export const updateFunctionTypeNode = Debug.deprecate(factory.updateFunctionTypeNode, factoryDeprecation);
 
     /** @deprecated Use `factory.createConstructorTypeNode` or the factory supplied by your transformation context instead. */
-    export const createConstructorTypeNode = Debug.deprecate(factory.createConstructorTypeNode, factoryDeprecation);
+    export const createConstructorTypeNode = Debug.deprecate((
+        typeParameters: readonly TypeParameterDeclaration[] | undefined,
+        parameters: readonly ParameterDeclaration[],
+        type: TypeNode
+    ) => {
+        return factory.createConstructorTypeNode(/*modifiers*/ undefined, typeParameters, parameters, type);
+    }, factoryDeprecation);
 
     /** @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. */
-    export const updateConstructorTypeNode = Debug.deprecate(factory.updateConstructorTypeNode, factoryDeprecation);
+    export const updateConstructorTypeNode = Debug.deprecate((
+        node: ConstructorTypeNode,
+        typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
+        parameters: NodeArray<ParameterDeclaration>,
+        type: TypeNode
+    ) => {
+        return factory.updateConstructorTypeNode(node, node.modifiers, typeParameters, parameters, type);
+    }, factoryDeprecation);
 
     /** @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. */
     export const createTypeQueryNode = Debug.deprecate(factory.createTypeQueryNode, factoryDeprecation);
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 0ebe2d0bec697..50b35745a0664 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -5042,23 +5042,28 @@ namespace ts {
                         returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
                     }
                 }
+                let modifiers = options?.modifiers;
+                if ((kind === SyntaxKind.ConstructorType) && signature.flags & SignatureFlags.Abstract) {
+                    const flags = modifiersToFlags(modifiers);
+                    modifiers = factory.createModifiersFromModifierFlags(flags | ModifierFlags.Abstract);
+                }
                 context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum
 
                 const node =
                     kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) :
                     kind === SyntaxKind.ConstructSignature ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) :
-                    kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(options?.modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
-                    kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, options?.modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
-                    kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, options?.modifiers, parameters, /*body*/ undefined) :
-                    kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, options?.modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
-                    kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, options?.modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
-                    kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, options?.modifiers, parameters, returnTypeNode) :
+                    kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) :
+                    kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
+                    kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) :
+                    kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) :
+                    kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) :
+                    kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, modifiers, parameters, returnTypeNode) :
                     kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) :
                     kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
-                    kind === SyntaxKind.ConstructorType ? factory.createConstructorTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
-                    kind === SyntaxKind.FunctionDeclaration ? factory.createFunctionDeclaration(/*decorators*/ undefined, options?.modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
-                    kind === SyntaxKind.FunctionExpression ? factory.createFunctionExpression(options?.modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, factory.createBlock([])) :
-                    kind === SyntaxKind.ArrowFunction ? factory.createArrowFunction(options?.modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, factory.createBlock([])) :
+                    kind === SyntaxKind.ConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) :
+                    kind === SyntaxKind.FunctionDeclaration ? factory.createFunctionDeclaration(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) :
+                    kind === SyntaxKind.FunctionExpression ? factory.createFunctionExpression(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, factory.createBlock([])) :
+                    kind === SyntaxKind.ArrowFunction ? factory.createArrowFunction(modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, factory.createBlock([])) :
                     Debug.assertNever(kind);
 
                 if (typeArguments) {
@@ -5760,6 +5765,7 @@ namespace ts {
                         if (isJSDocConstructSignature(node)) {
                             let newTypeNode: TypeNode | undefined;
                             return factory.createConstructorTypeNode(
+                                node.modifiers,
                                 visitNodes(node.typeParameters, visitExistingNodeTreeSymbols),
                                 mapDefined(node.parameters, (p, i) => p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration(
                                     /*decorators*/ undefined,
@@ -8794,7 +8800,10 @@ namespace ts {
             const signatures = getSignaturesOfType(type, SignatureKind.Construct);
             if (signatures.length === 1) {
                 const s = signatures[0];
-                return !s.typeParameters && s.parameters.length === 1 && signatureHasRestParameter(s) && getElementTypeOfArrayType(getTypeOfParameter(s.parameters[0])) === anyType;
+                if (!s.typeParameters && s.parameters.length === 1 && signatureHasRestParameter(s)) {
+                    const paramType = getTypeOfParameter(s.parameters[0]);
+                    return isTypeAny(paramType) || getElementTypeOfArrayType(paramType) === anyType;
+                }
             }
             return false;
         }
@@ -9795,8 +9804,10 @@ namespace ts {
         function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
             const baseConstructorType = getBaseConstructorTypeOfClass(classType);
             const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
+            const declaration = getClassLikeDeclarationOfSymbol(classType.symbol);
+            const isAbstract = !!declaration && hasSyntacticModifier(declaration, ModifierFlags.Abstract);
             if (baseSignatures.length === 0) {
-                return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None)];
+                return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, isAbstract ? SignatureFlags.Abstract : SignatureFlags.None)];
             }
             const baseTypeNode = getBaseTypeNodeOfClass(classType)!;
             const isJavaScript = isInJSFile(baseTypeNode);
@@ -9810,6 +9821,7 @@ namespace ts {
                     const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig);
                     sig.typeParameters = classType.localTypeParameters;
                     sig.resolvedReturnType = classType;
+                    sig.flags = isAbstract ? sig.flags | SignatureFlags.Abstract : sig.flags & ~SignatureFlags.Abstract;
                     result.push(sig);
                 }
             }
@@ -11313,6 +11325,10 @@ namespace ts {
                 if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) {
                     flags |= SignatureFlags.HasRestParameter;
                 }
+                if (isConstructorTypeNode(declaration) && hasSyntacticModifier(declaration, ModifierFlags.Abstract) ||
+                    isConstructorDeclaration(declaration) && hasSyntacticModifier(declaration.parent, ModifierFlags.Abstract)) {
+                    flags |= SignatureFlags.Abstract;
+                }
                 links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters,
                     /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined,
                     minArgumentCount, flags);
@@ -17359,7 +17375,9 @@ namespace ts {
                     SignatureKind.Call : kind);
 
                 if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) {
-                    if (isAbstractConstructorType(source) && !isAbstractConstructorType(target)) {
+                    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,
@@ -26552,10 +26570,14 @@ 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.
+                // If the expression is a class of abstract type, or an abstract construct signature, 
+                // 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 (constructSignatures.some(signature => signature.flags & SignatureFlags.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)) {
                     error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class);
@@ -30698,14 +30720,13 @@ namespace ts {
                 const implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
                 return implementationSharesContainerWithFirstOverload ? implementation! : overloads[0];
             }
-
+    
             function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void {
                 // Error if some overloads have a flag that is not shared by all overloads. To find the
                 // deviations, we XOR someOverloadFlags with allOverloadFlags
                 const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
                 if (someButNotAllOverloadFlags !== 0) {
                     const canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck);
-
                     forEach(overloads, o => {
                         const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
                         if (deviation & ModifierFlags.Export) {
@@ -30723,7 +30744,7 @@ namespace ts {
                     });
                 }
             }
-
+    
             function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void {
                 if (someHaveQuestionToken !== allHaveQuestionToken) {
                     const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation));
@@ -35163,8 +35184,8 @@ namespace ts {
                     return checkPropertyDeclaration(<PropertyDeclaration>node);
                 case SyntaxKind.PropertySignature:
                     return checkPropertySignature(<PropertySignature>node);
-                case SyntaxKind.FunctionType:
                 case SyntaxKind.ConstructorType:
+                case SyntaxKind.FunctionType:
                 case SyntaxKind.CallSignature:
                 case SyntaxKind.ConstructSignature:
                 case SyntaxKind.IndexSignature:
@@ -37385,7 +37406,8 @@ namespace ts {
                         if (flags & ModifierFlags.Abstract) {
                             return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract");
                         }
-                        if (node.kind !== SyntaxKind.ClassDeclaration) {
+                        if (node.kind !== SyntaxKind.ClassDeclaration &&
+                            node.kind !== SyntaxKind.ConstructorType) {
                             if (node.kind !== SyntaxKind.MethodDeclaration &&
                                 node.kind !== SyntaxKind.PropertyDeclaration &&
                                 node.kind !== SyntaxKind.GetAccessor &&
@@ -37493,6 +37515,7 @@ namespace ts {
                         case SyntaxKind.FunctionDeclaration:
                             return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword);
                         case SyntaxKind.ClassDeclaration:
+                        case SyntaxKind.ConstructorType:
                             return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword);
                         case SyntaxKind.InterfaceDeclaration:
                         case SyntaxKind.VariableStatement:
@@ -37502,7 +37525,6 @@ namespace ts {
                             return nodeHasAnyModifiersExcept(node, SyntaxKind.ConstKeyword);
                         default:
                             Debug.fail();
-                            return false;
                     }
             }
         }
diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts
index 62b01e816a977..7d60ebd6e2c95 100644
--- a/src/compiler/debug.ts
+++ b/src/compiler/debug.ts
@@ -367,6 +367,10 @@ namespace ts {
             return formatEnum(flags, (<any>ts).TypeFlags, /*isFlags*/ true);
         }
 
+        export function formatSignatureFlags(flags: SignatureFlags | undefined): string {
+            return formatEnum(flags, (<any>ts).SignatureFlags, /*isFlags*/ true);
+        }
+
         export function formatObjectFlags(flags: ObjectFlags | undefined): string {
             return formatEnum(flags, (<any>ts).ObjectFlags, /*isFlags*/ true);
         }
@@ -424,6 +428,11 @@ namespace ts {
                 __debugTypeToString: { value(this: Type) { return this.checker.typeToString(this); } },
             });
 
+            Object.defineProperties(objectAllocator.getSignatureConstructor().prototype, {
+                __debugFlags: { get(this: Signature) { return formatSignatureFlags(this.flags); } },
+                __debugSignatureToString: { value(this: Signature) { return this.checker?.signatureToString(this) } }
+            });
+
             const nodeConstructors = [
                 objectAllocator.getNodeConstructor(),
                 objectAllocator.getIdentifierConstructor(),
diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index c9829f914fbc2..bda0118bbc31d 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -2066,6 +2066,7 @@ namespace ts {
 
         function emitConstructorType(node: ConstructorTypeNode) {
             pushNameGenerationScope(node);
+            emitModifiers(node, node.modifiers);
             writeKeyword("new");
             writeSpace();
             emitTypeParameters(node, node.typeParameters);
diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts
index 4814bf679e074..0b2c60e863778 100644
--- a/src/compiler/factory/nodeFactory.ts
+++ b/src/compiler/factory/nodeFactory.ts
@@ -1648,6 +1648,7 @@ namespace ts {
 
         // @api
         function createConstructorTypeNode(
+            modifiers: readonly Modifier[] | undefined,
             typeParameters: readonly TypeParameterDeclaration[] | undefined,
             parameters: readonly ParameterDeclaration[],
             type: TypeNode | undefined
@@ -1655,7 +1656,7 @@ namespace ts {
             const node = createBaseSignatureDeclaration<ConstructorTypeNode>(
                 SyntaxKind.ConstructorType,
                 /*decorators*/ undefined,
-                /*modifiers*/ undefined,
+                modifiers,
                 /*name*/ undefined,
                 typeParameters,
                 parameters,
@@ -1668,14 +1669,16 @@ namespace ts {
         // @api
         function updateConstructorTypeNode(
             node: ConstructorTypeNode,
+            modifiers: readonly Modifier[] | undefined,
             typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
             parameters: NodeArray<ParameterDeclaration>,
             type: TypeNode | undefined
         ) {
-            return node.typeParameters !== typeParameters
+            return node.modifiers !== modifiers
+                || node.typeParameters !== typeParameters
                 || node.parameters !== parameters
                 || node.type !== type
-                ? updateBaseSignatureDeclaration(createConstructorTypeNode(typeParameters, parameters, type), node)
+                ? updateBaseSignatureDeclaration(createConstructorTypeNode(modifiers, typeParameters, parameters, type), node)
                 : node;
         }
 
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index db6b562a70e20..e8029ae268f83 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -3168,16 +3168,29 @@ namespace ts {
             return finishNode(factory.createParenthesizedType(type), pos);
         }
 
+        function parseModifiersForConstructorType(): NodeArray<Modifier> | undefined {
+            let modifiers: NodeArray<Modifier> | undefined;
+            if (token() === SyntaxKind.AbstractKeyword) {
+                const pos = getNodePos();
+                nextToken();
+                const modifier = finishNode(factory.createToken(SyntaxKind.AbstractKeyword), pos);
+                modifiers = createNodeArray<Modifier>([modifier], pos);
+            }
+            return modifiers;
+        }
+
         function parseFunctionOrConstructorType(): TypeNode {
             const pos = getNodePos();
             const hasJSDoc = hasPrecedingJSDocComment();
+            const modifiers = parseModifiersForConstructorType();
             const isConstructorType = parseOptional(SyntaxKind.NewKeyword);
             const typeParameters = parseTypeParameters();
             const parameters = parseParameters(SignatureFlags.Type);
             const type = parseReturnType(SyntaxKind.EqualsGreaterThanToken, /*isType*/ false);
             const node = isConstructorType
-                ? factory.createConstructorTypeNode(typeParameters, parameters, type)
+                ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, type)
                 : factory.createFunctionTypeNode(typeParameters, parameters, type);
+            if (!isConstructorType) (node as Mutable<Node>).modifiers = modifiers;
             return withJSDoc(finishNode(node, pos), hasJSDoc);
         }
 
@@ -3451,6 +3464,16 @@ namespace ts {
             return token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType);
         }
 
+        function nextTokenIsNewKeyword(): boolean {
+            nextToken();
+            return token() === SyntaxKind.NewKeyword;
+        }
+
+        function isStartOfConstructorType(): boolean {
+            return token() === SyntaxKind.NewKeyword ||
+                token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword);
+        }
+
         function skipParameterStart(): boolean {
             if (isModifierKind(token())) {
                 // Skip modifiers
@@ -3533,7 +3556,7 @@ namespace ts {
         }
 
         function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
-            if (isStartOfFunctionType() || token() === SyntaxKind.NewKeyword) {
+            if (isStartOfFunctionType() || isStartOfConstructorType()) {
                 return parseFunctionOrConstructorType();
             }
             const pos = getNodePos();
diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts
index ba4c01beb8ba8..b25d12c9cb351 100644
--- a/src/compiler/transformers/declarations.ts
+++ b/src/compiler/transformers/declarations.ts
@@ -1009,7 +1009,7 @@ namespace ts {
                         return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
                     }
                     case SyntaxKind.ConstructorType: {
-                        return cleanup(factory.updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
+                        return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
                     }
                     case SyntaxKind.ImportType: {
                         if (!isLiteralImportTypeNode(input)) return cleanup(input);
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 286c8145c3cb1..54cf3cd339797 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -5311,16 +5311,21 @@ namespace ts {
     /* @internal */
     export const enum SignatureFlags {
         None = 0,
+
+        // Propagating flags
         HasRestParameter = 1 << 0,          // Indicates last parameter is rest parameter
         HasLiteralTypes = 1 << 1,           // Indicates signature is specialized
-        IsInnerCallChain = 1 << 2,          // Indicates signature comes from a CallChain nested in an outer OptionalChain
-        IsOuterCallChain = 1 << 3,          // Indicates signature comes from a CallChain that is the outermost chain of an optional expression
-        IsUntypedSignatureInJSFile = 1 << 4, // Indicates signature is from a js file and has no types
+        Abstract = 1 << 2,                  // Indicates signature comes from an abstract class, abstract construct signature, or abstract constructor type
+
+        // Non-propagating flags
+        IsInnerCallChain = 1 << 3,          // Indicates signature comes from a CallChain nested in an outer OptionalChain
+        IsOuterCallChain = 1 << 4,          // Indicates signature comes from a CallChain that is the outermost chain of an optional expression
+        IsUntypedSignatureInJSFile = 1 << 5, // Indicates signature is from a js file and has no types
 
-        // We do not propagate `IsInnerCallChain` to instantiated signatures, as that would result in us
+        // We do not propagate `IsInnerCallChain` or `IsOuterCallChain` to instantiated signatures, as that would result in us
         // attempting to add `| undefined` on each recursive call to `getReturnTypeOfSignature` when
         // instantiating the return type.
-        PropagatingFlags = HasRestParameter | HasLiteralTypes,
+        PropagatingFlags = HasRestParameter | HasLiteralTypes | Abstract,
 
         CallChainFlags = IsInnerCallChain | IsOuterCallChain,
     }
@@ -6666,8 +6671,8 @@ namespace ts {
         updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined): TypeReferenceNode;
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
-        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
-        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 90bc40b4aebc4..237785ac47c91 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -4622,7 +4622,7 @@ namespace ts {
         return flags;
     }
 
-    export function modifiersToFlags(modifiers: NodeArray<Modifier> | undefined) {
+    export function modifiersToFlags(modifiers: readonly Modifier[] | undefined) {
         let flags = ModifierFlags.None;
         if (modifiers) {
             for (const modifier of modifiers) {
@@ -5319,11 +5319,6 @@ namespace ts {
         });
     }
 
-    // Return true if the given type is the constructor type for an abstract class
-    export function isAbstractConstructorType(type: Type): boolean {
-        return !!(getObjectFlags(type) & ObjectFlags.Anonymous) && !!type.symbol && isAbstractConstructorSymbol(type.symbol);
-    }
-
     export function isAbstractConstructorSymbol(symbol: Symbol): boolean {
         if (symbol.flags & SymbolFlags.Class) {
             const declaration = getClassLikeDeclarationOfSymbol(symbol);
diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts
index 86651c8e433d0..c488ff8c16454 100644
--- a/src/compiler/visitorPublic.ts
+++ b/src/compiler/visitorPublic.ts
@@ -483,6 +483,7 @@ namespace ts {
 
             case SyntaxKind.ConstructorType:
                 return factory.updateConstructorTypeNode(<ConstructorTypeNode>node,
+                    nodesVisitor((<ConstructorTypeNode>node).modifiers, visitor, isModifier),
                     nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
                     nodesVisitor((<ConstructorTypeNode>node).parameters, visitor, isParameterDeclaration),
                     nodeVisitor((<ConstructorTypeNode>node).type, visitor, isTypeNode));
diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts
index 544cf09041d20..d66023294c1f2 100644
--- a/src/lib/es5.d.ts
+++ b/src/lib/es5.d.ts
@@ -1496,7 +1496,7 @@ type Parameters<T extends (...args: any) => any> = T extends (...args: infer P)
 /**
  * Obtain the parameters of a constructor function type in a tuple
  */
-type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
+type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
 
 /**
  * Obtain the return type of a function type
@@ -1506,7 +1506,7 @@ type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => i
 /**
  * Obtain the return type of a constructor function type
  */
-type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
+type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
 
 /**
  * Marker for contextual 'this' type
diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts
index d62be2649031a..276b1fa8b093b 100644
--- a/src/services/symbolDisplay.ts
+++ b/src/services/symbolDisplay.ts
@@ -194,6 +194,10 @@ namespace ts.SymbolDisplay {
                         pushSymbolKind(symbolKind);
                         displayParts.push(spacePart());
                         if (useConstructSignatures) {
+                            if (signature.flags & SignatureFlags.Abstract) {
+                                displayParts.push(keywordPart(SyntaxKind.AbstractKeyword));
+                                displayParts.push(spacePart());
+                            }
                             displayParts.push(keywordPart(SyntaxKind.NewKeyword));
                             displayParts.push(spacePart());
                         }
@@ -219,6 +223,10 @@ namespace ts.SymbolDisplay {
                                 displayParts.push(lineBreakPart());
                             }
                             if (useConstructSignatures) {
+                                if (signature.flags & SignatureFlags.Abstract) {
+                                    displayParts.push(keywordPart(SyntaxKind.AbstractKeyword));
+                                    displayParts.push(spacePart());
+                                }
                                 displayParts.push(keywordPart(SyntaxKind.NewKeyword));
                                 displayParts.push(spacePart());
                             }
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index f03ad8d3f6849..6320f680ff8e8 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -3148,8 +3148,8 @@ declare namespace ts {
         updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined): TypeReferenceNode;
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
-        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
-        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;
@@ -10246,9 +10246,9 @@ declare namespace ts {
     /** @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. */
     const updateEnumDeclaration: (node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]) => EnumDeclaration;
     /** @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. */
-    const createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration;
+    const createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBlock | NamespaceDeclaration | Identifier | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration;
     /** @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. */
-    const updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration;
+    const updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBlock | NamespaceDeclaration | Identifier | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration;
     /** @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. */
     const createModuleBlock: (statements: readonly Statement[]) => ModuleBlock;
     /** @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. */
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index 989a845468197..e007b7cbed0fa 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -3148,8 +3148,8 @@ declare namespace ts {
         updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined): TypeReferenceNode;
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
-        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
-        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;
@@ -6692,9 +6692,9 @@ declare namespace ts {
     /** @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. */
     const updateEnumDeclaration: (node: EnumDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, members: readonly EnumMember[]) => EnumDeclaration;
     /** @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. */
-    const createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration;
+    const createModuleDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBlock | NamespaceDeclaration | Identifier | JSDocNamespaceDeclaration | undefined, flags?: NodeFlags | undefined) => ModuleDeclaration;
     /** @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. */
-    const updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: Identifier | ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration;
+    const updateModuleDeclaration: (node: ModuleDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: ModuleName, body: ModuleBlock | NamespaceDeclaration | Identifier | JSDocNamespaceDeclaration | undefined) => ModuleDeclaration;
     /** @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. */
     const createModuleBlock: (statements: readonly Statement[]) => ModuleBlock;
     /** @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. */
diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt
index 3779d91bf2b01..82f384705352b 100644
--- a/tests/baselines/reference/inferTypes1.errors.txt
+++ b/tests/baselines/reference/inferTypes1.errors.txt
@@ -1,23 +1,23 @@
-tests/cases/conformance/types/conditional/inferTypes1.ts(31,23): error TS2344: Type 'string' does not satisfy the constraint '(...args: any) => any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(32,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(36,23): error TS2344: Type 'string' does not satisfy the constraint '(...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(37,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any) => any'.
   Type 'Function' provides no match for the signature '(...args: any): any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(38,25): error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any) => any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(39,25): error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(43,25): error TS2344: Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(44,25): error TS2344: Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.
   Type 'Function' provides no match for the signature 'new (...args: any): any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(47,25): error TS2344: Type '(x: string, y: string) => number' does not satisfy the constraint '(x: any) => any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(48,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(55,25): error TS2344: Type '(x: string, y: string) => number' does not satisfy the constraint '(x: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(56,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'.
   Type 'Function' provides no match for the signature '(x: any): any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(74,12): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
-tests/cases/conformance/types/conditional/inferTypes1.ts(75,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
-tests/cases/conformance/types/conditional/inferTypes1.ts(75,41): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
-tests/cases/conformance/types/conditional/inferTypes1.ts(75,51): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
-tests/cases/conformance/types/conditional/inferTypes1.ts(76,15): error TS2304: Cannot find name 'U'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(76,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(76,43): error TS2304: Cannot find name 'U'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(76,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(83,44): error TS2344: Type 'U' does not satisfy the constraint 'string'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(82,12): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
+tests/cases/conformance/types/conditional/inferTypes1.ts(83,15): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
+tests/cases/conformance/types/conditional/inferTypes1.ts(83,41): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
+tests/cases/conformance/types/conditional/inferTypes1.ts(83,51): error TS1338: 'infer' declarations are only permitted in the 'extends' clause of a conditional type.
+tests/cases/conformance/types/conditional/inferTypes1.ts(84,15): error TS2304: Cannot find name 'U'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(84,15): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(84,43): error TS2304: Cannot find name 'U'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(84,43): error TS4081: Exported type alias 'T62' has or is using private name 'U'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(91,44): error TS2344: Type 'U' does not satisfy the constraint 'string'.
   Type 'number' is not assignable to type 'string'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(145,40): error TS2322: Type 'T' is not assignable to type 'string | number | symbol'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322: Type 'T' is not assignable to type 'string | number | symbol'.
   Type 'T' is not assignable to type 'symbol'.
 
 
@@ -45,6 +45,11 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(145,40): error TS2322:
         y = 0;
     }
     
+    abstract class Abstract {
+        x = 0;
+        y = 0;
+    }
+    
     type T10 = ReturnType<() => string>;  // string
     type T11 = ReturnType<(s: string) => void>;  // void
     type T12 = ReturnType<(<T>() => T)>;  // {}
@@ -66,11 +71,14 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(145,40): error TS2322:
     type U12 = InstanceType<never>;  // never
     type U13 = InstanceType<string>;  // Error
                             ~~~~~~
-!!! error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any) => any'.
+!!! error TS2344: Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.
     type U14 = InstanceType<Function>;  // Error
                             ~~~~~~~~
-!!! error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any) => any'.
+!!! error TS2344: Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.
 !!! error TS2344:   Type 'Function' provides no match for the signature 'new (...args: any): any'.
+    type U15 = InstanceType<typeof Abstract>;  // Abstract
+    type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
+    type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
     
     type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
     
diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js
index 01dc5a797f224..e3e2b88dd4edb 100644
--- a/tests/baselines/reference/inferTypes1.js
+++ b/tests/baselines/reference/inferTypes1.js
@@ -22,6 +22,11 @@ class C {
     y = 0;
 }
 
+abstract class Abstract {
+    x = 0;
+    y = 0;
+}
+
 type T10 = ReturnType<() => string>;  // string
 type T11 = ReturnType<(s: string) => void>;  // void
 type T12 = ReturnType<(<T>() => T)>;  // {}
@@ -38,6 +43,9 @@ type U11 = InstanceType<any>;  // any
 type U12 = InstanceType<never>;  // never
 type U13 = InstanceType<string>;  // Error
 type U14 = InstanceType<Function>;  // Error
+type U15 = InstanceType<typeof Abstract>;  // Abstract
+type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
+type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
 
 type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
 
@@ -191,6 +199,13 @@ var C = /** @class */ (function () {
     }
     return C;
 }());
+var Abstract = /** @class */ (function () {
+    function Abstract() {
+        this.x = 0;
+        this.y = 0;
+    }
+    return Abstract;
+}());
 var z1 = ex.customClass;
 var z2 = ex.obj.nested.attr;
 // Repros from #26856
diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols
index 609a0093290a7..a7e2b0ac5d8f6 100644
--- a/tests/baselines/reference/inferTypes1.symbols
+++ b/tests/baselines/reference/inferTypes1.symbols
@@ -74,669 +74,702 @@ class C {
 >y : Symbol(C.y, Decl(inferTypes1.ts, 19, 10))
 }
 
+abstract class Abstract {
+>Abstract : Symbol(Abstract, Decl(inferTypes1.ts, 21, 1))
+
+    x = 0;
+>x : Symbol(Abstract.x, Decl(inferTypes1.ts, 23, 25))
+
+    y = 0;
+>y : Symbol(Abstract.y, Decl(inferTypes1.ts, 24, 10))
+}
+
 type T10 = ReturnType<() => string>;  // string
->T10 : Symbol(T10, Decl(inferTypes1.ts, 21, 1))
+>T10 : Symbol(T10, Decl(inferTypes1.ts, 26, 1))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 
 type T11 = ReturnType<(s: string) => void>;  // void
->T11 : Symbol(T11, Decl(inferTypes1.ts, 23, 36))
+>T11 : Symbol(T11, Decl(inferTypes1.ts, 28, 36))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->s : Symbol(s, Decl(inferTypes1.ts, 24, 23))
+>s : Symbol(s, Decl(inferTypes1.ts, 29, 23))
 
 type T12 = ReturnType<(<T>() => T)>;  // {}
->T12 : Symbol(T12, Decl(inferTypes1.ts, 24, 43))
+>T12 : Symbol(T12, Decl(inferTypes1.ts, 29, 43))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->T : Symbol(T, Decl(inferTypes1.ts, 25, 24))
->T : Symbol(T, Decl(inferTypes1.ts, 25, 24))
+>T : Symbol(T, Decl(inferTypes1.ts, 30, 24))
+>T : Symbol(T, Decl(inferTypes1.ts, 30, 24))
 
 type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>;  // number[]
->T13 : Symbol(T13, Decl(inferTypes1.ts, 25, 36))
+>T13 : Symbol(T13, Decl(inferTypes1.ts, 30, 36))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->T : Symbol(T, Decl(inferTypes1.ts, 26, 24))
->U : Symbol(U, Decl(inferTypes1.ts, 26, 36))
->U : Symbol(U, Decl(inferTypes1.ts, 26, 36))
->T : Symbol(T, Decl(inferTypes1.ts, 26, 24))
+>T : Symbol(T, Decl(inferTypes1.ts, 31, 24))
+>U : Symbol(U, Decl(inferTypes1.ts, 31, 36))
+>U : Symbol(U, Decl(inferTypes1.ts, 31, 36))
+>T : Symbol(T, Decl(inferTypes1.ts, 31, 24))
 
 type T14 = ReturnType<typeof f1>;  // { a: number, b: string }
->T14 : Symbol(T14, Decl(inferTypes1.ts, 26, 66))
+>T14 : Symbol(T14, Decl(inferTypes1.ts, 31, 66))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 >f1 : Symbol(f1, Decl(inferTypes1.ts, 12, 27))
 
 type T15 = ReturnType<any>;  // any
->T15 : Symbol(T15, Decl(inferTypes1.ts, 27, 33))
+>T15 : Symbol(T15, Decl(inferTypes1.ts, 32, 33))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 
 type T16 = ReturnType<never>;  // never
->T16 : Symbol(T16, Decl(inferTypes1.ts, 28, 27))
+>T16 : Symbol(T16, Decl(inferTypes1.ts, 33, 27))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 
 type T17 = ReturnType<string>;  // Error
->T17 : Symbol(T17, Decl(inferTypes1.ts, 29, 29))
+>T17 : Symbol(T17, Decl(inferTypes1.ts, 34, 29))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 
 type T18 = ReturnType<Function>;  // Error
->T18 : Symbol(T18, Decl(inferTypes1.ts, 30, 30))
+>T18 : Symbol(T18, Decl(inferTypes1.ts, 35, 30))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
 >Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
 
 type T19<T extends any[]> = ReturnType<(x: string, ...args: T) => T[]>;  // T[]
->T19 : Symbol(T19, Decl(inferTypes1.ts, 31, 32))
->T : Symbol(T, Decl(inferTypes1.ts, 32, 9))
+>T19 : Symbol(T19, Decl(inferTypes1.ts, 36, 32))
+>T : Symbol(T, Decl(inferTypes1.ts, 37, 9))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->x : Symbol(x, Decl(inferTypes1.ts, 32, 40))
->args : Symbol(args, Decl(inferTypes1.ts, 32, 50))
->T : Symbol(T, Decl(inferTypes1.ts, 32, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 32, 9))
+>x : Symbol(x, Decl(inferTypes1.ts, 37, 40))
+>args : Symbol(args, Decl(inferTypes1.ts, 37, 50))
+>T : Symbol(T, Decl(inferTypes1.ts, 37, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 37, 9))
 
 type U10 = InstanceType<typeof C>;  // C
->U10 : Symbol(U10, Decl(inferTypes1.ts, 32, 71))
+>U10 : Symbol(U10, Decl(inferTypes1.ts, 37, 71))
 >InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
 >C : Symbol(C, Decl(inferTypes1.ts, 16, 1))
 
 type U11 = InstanceType<any>;  // any
->U11 : Symbol(U11, Decl(inferTypes1.ts, 34, 34))
+>U11 : Symbol(U11, Decl(inferTypes1.ts, 39, 34))
 >InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
 
 type U12 = InstanceType<never>;  // never
->U12 : Symbol(U12, Decl(inferTypes1.ts, 35, 29))
+>U12 : Symbol(U12, Decl(inferTypes1.ts, 40, 29))
 >InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
 
 type U13 = InstanceType<string>;  // Error
->U13 : Symbol(U13, Decl(inferTypes1.ts, 36, 31))
+>U13 : Symbol(U13, Decl(inferTypes1.ts, 41, 31))
 >InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
 
 type U14 = InstanceType<Function>;  // Error
->U14 : Symbol(U14, Decl(inferTypes1.ts, 37, 32))
+>U14 : Symbol(U14, Decl(inferTypes1.ts, 42, 32))
 >InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
 >Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
 
+type U15 = InstanceType<typeof Abstract>;  // Abstract
+>U15 : Symbol(U15, Decl(inferTypes1.ts, 43, 34))
+>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
+>Abstract : Symbol(Abstract, Decl(inferTypes1.ts, 21, 1))
+
+type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
+>U16 : Symbol(U16, Decl(inferTypes1.ts, 44, 41))
+>T : Symbol(T, Decl(inferTypes1.ts, 45, 9))
+>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(inferTypes1.ts, 45, 46))
+>args : Symbol(args, Decl(inferTypes1.ts, 45, 56))
+>T : Symbol(T, Decl(inferTypes1.ts, 45, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 45, 9))
+
+type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
+>U17 : Symbol(U17, Decl(inferTypes1.ts, 45, 77))
+>T : Symbol(T, Decl(inferTypes1.ts, 46, 9))
+>InstanceType : Symbol(InstanceType, Decl(lib.es5.d.ts, --, --))
+>x : Symbol(x, Decl(inferTypes1.ts, 46, 55))
+>args : Symbol(args, Decl(inferTypes1.ts, 46, 65))
+>T : Symbol(T, Decl(inferTypes1.ts, 46, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 46, 9))
+
 type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
->T : Symbol(T, Decl(inferTypes1.ts, 40, 18))
->x : Symbol(x, Decl(inferTypes1.ts, 40, 29))
->T : Symbol(T, Decl(inferTypes1.ts, 40, 18))
->a : Symbol(a, Decl(inferTypes1.ts, 40, 58))
->A : Symbol(A, Decl(inferTypes1.ts, 40, 66))
->A : Symbol(A, Decl(inferTypes1.ts, 40, 66))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
+>T : Symbol(T, Decl(inferTypes1.ts, 48, 18))
+>x : Symbol(x, Decl(inferTypes1.ts, 48, 29))
+>T : Symbol(T, Decl(inferTypes1.ts, 48, 18))
+>a : Symbol(a, Decl(inferTypes1.ts, 48, 58))
+>A : Symbol(A, Decl(inferTypes1.ts, 48, 66))
+>A : Symbol(A, Decl(inferTypes1.ts, 48, 66))
 
 type T20 = ArgumentType<() => void>;  // {}
->T20 : Symbol(T20, Decl(inferTypes1.ts, 40, 87))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
+>T20 : Symbol(T20, Decl(inferTypes1.ts, 48, 87))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
 
 type T21 = ArgumentType<(x: string) => number>;  // string
->T21 : Symbol(T21, Decl(inferTypes1.ts, 42, 36))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
->x : Symbol(x, Decl(inferTypes1.ts, 43, 25))
+>T21 : Symbol(T21, Decl(inferTypes1.ts, 50, 36))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
+>x : Symbol(x, Decl(inferTypes1.ts, 51, 25))
 
 type T22 = ArgumentType<(x?: string) => number>;  // string | undefined
->T22 : Symbol(T22, Decl(inferTypes1.ts, 43, 47))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
->x : Symbol(x, Decl(inferTypes1.ts, 44, 25))
+>T22 : Symbol(T22, Decl(inferTypes1.ts, 51, 47))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
+>x : Symbol(x, Decl(inferTypes1.ts, 52, 25))
 
 type T23 = ArgumentType<(...args: string[]) => number>;  // string
->T23 : Symbol(T23, Decl(inferTypes1.ts, 44, 48))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
->args : Symbol(args, Decl(inferTypes1.ts, 45, 25))
+>T23 : Symbol(T23, Decl(inferTypes1.ts, 52, 48))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
+>args : Symbol(args, Decl(inferTypes1.ts, 53, 25))
 
 type T24 = ArgumentType<(x: string, y: string) => number>;  // Error
->T24 : Symbol(T24, Decl(inferTypes1.ts, 45, 55))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
->x : Symbol(x, Decl(inferTypes1.ts, 46, 25))
->y : Symbol(y, Decl(inferTypes1.ts, 46, 35))
+>T24 : Symbol(T24, Decl(inferTypes1.ts, 53, 55))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
+>x : Symbol(x, Decl(inferTypes1.ts, 54, 25))
+>y : Symbol(y, Decl(inferTypes1.ts, 54, 35))
 
 type T25 = ArgumentType<Function>;  // Error
->T25 : Symbol(T25, Decl(inferTypes1.ts, 46, 58))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
+>T25 : Symbol(T25, Decl(inferTypes1.ts, 54, 58))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
 >Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
 
 type T26 = ArgumentType<any>;  // any
->T26 : Symbol(T26, Decl(inferTypes1.ts, 47, 34))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
+>T26 : Symbol(T26, Decl(inferTypes1.ts, 55, 34))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
 
 type T27 = ArgumentType<never>;  // never
->T27 : Symbol(T27, Decl(inferTypes1.ts, 48, 29))
->ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 38, 34))
+>T27 : Symbol(T27, Decl(inferTypes1.ts, 56, 29))
+>ArgumentType : Symbol(ArgumentType, Decl(inferTypes1.ts, 46, 86))
 
 type X1<T extends { x: any, y: any }> = T extends { x: infer X, y: infer Y } ? [X, Y] : any;
->X1 : Symbol(X1, Decl(inferTypes1.ts, 49, 31))
->T : Symbol(T, Decl(inferTypes1.ts, 51, 8))
->x : Symbol(x, Decl(inferTypes1.ts, 51, 19))
->y : Symbol(y, Decl(inferTypes1.ts, 51, 27))
->T : Symbol(T, Decl(inferTypes1.ts, 51, 8))
->x : Symbol(x, Decl(inferTypes1.ts, 51, 51))
->X : Symbol(X, Decl(inferTypes1.ts, 51, 60))
->y : Symbol(y, Decl(inferTypes1.ts, 51, 63))
->Y : Symbol(Y, Decl(inferTypes1.ts, 51, 72))
->X : Symbol(X, Decl(inferTypes1.ts, 51, 60))
->Y : Symbol(Y, Decl(inferTypes1.ts, 51, 72))
+>X1 : Symbol(X1, Decl(inferTypes1.ts, 57, 31))
+>T : Symbol(T, Decl(inferTypes1.ts, 59, 8))
+>x : Symbol(x, Decl(inferTypes1.ts, 59, 19))
+>y : Symbol(y, Decl(inferTypes1.ts, 59, 27))
+>T : Symbol(T, Decl(inferTypes1.ts, 59, 8))
+>x : Symbol(x, Decl(inferTypes1.ts, 59, 51))
+>X : Symbol(X, Decl(inferTypes1.ts, 59, 60))
+>y : Symbol(y, Decl(inferTypes1.ts, 59, 63))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 59, 72))
+>X : Symbol(X, Decl(inferTypes1.ts, 59, 60))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 59, 72))
 
 type T30 = X1<{ x: any, y: any }>;  // [any, any]
->T30 : Symbol(T30, Decl(inferTypes1.ts, 51, 92))
->X1 : Symbol(X1, Decl(inferTypes1.ts, 49, 31))
->x : Symbol(x, Decl(inferTypes1.ts, 53, 15))
->y : Symbol(y, Decl(inferTypes1.ts, 53, 23))
+>T30 : Symbol(T30, Decl(inferTypes1.ts, 59, 92))
+>X1 : Symbol(X1, Decl(inferTypes1.ts, 57, 31))
+>x : Symbol(x, Decl(inferTypes1.ts, 61, 15))
+>y : Symbol(y, Decl(inferTypes1.ts, 61, 23))
 
 type T31 = X1<{ x: number, y: string }>;  // [number, string]
->T31 : Symbol(T31, Decl(inferTypes1.ts, 53, 34))
->X1 : Symbol(X1, Decl(inferTypes1.ts, 49, 31))
->x : Symbol(x, Decl(inferTypes1.ts, 54, 15))
->y : Symbol(y, Decl(inferTypes1.ts, 54, 26))
+>T31 : Symbol(T31, Decl(inferTypes1.ts, 61, 34))
+>X1 : Symbol(X1, Decl(inferTypes1.ts, 57, 31))
+>x : Symbol(x, Decl(inferTypes1.ts, 62, 15))
+>y : Symbol(y, Decl(inferTypes1.ts, 62, 26))
 
 type T32 = X1<{ x: number, y: string, z: boolean }>;  // [number, string]
->T32 : Symbol(T32, Decl(inferTypes1.ts, 54, 40))
->X1 : Symbol(X1, Decl(inferTypes1.ts, 49, 31))
->x : Symbol(x, Decl(inferTypes1.ts, 55, 15))
->y : Symbol(y, Decl(inferTypes1.ts, 55, 26))
->z : Symbol(z, Decl(inferTypes1.ts, 55, 37))
+>T32 : Symbol(T32, Decl(inferTypes1.ts, 62, 40))
+>X1 : Symbol(X1, Decl(inferTypes1.ts, 57, 31))
+>x : Symbol(x, Decl(inferTypes1.ts, 63, 15))
+>y : Symbol(y, Decl(inferTypes1.ts, 63, 26))
+>z : Symbol(z, Decl(inferTypes1.ts, 63, 37))
 
 type X2<T> = T extends { a: infer U, b: infer U } ? U : never;
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
->T : Symbol(T, Decl(inferTypes1.ts, 57, 8))
->T : Symbol(T, Decl(inferTypes1.ts, 57, 8))
->a : Symbol(a, Decl(inferTypes1.ts, 57, 24))
->U : Symbol(U, Decl(inferTypes1.ts, 57, 33), Decl(inferTypes1.ts, 57, 45))
->b : Symbol(b, Decl(inferTypes1.ts, 57, 36))
->U : Symbol(U, Decl(inferTypes1.ts, 57, 33), Decl(inferTypes1.ts, 57, 45))
->U : Symbol(U, Decl(inferTypes1.ts, 57, 33), Decl(inferTypes1.ts, 57, 45))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
+>T : Symbol(T, Decl(inferTypes1.ts, 65, 8))
+>T : Symbol(T, Decl(inferTypes1.ts, 65, 8))
+>a : Symbol(a, Decl(inferTypes1.ts, 65, 24))
+>U : Symbol(U, Decl(inferTypes1.ts, 65, 33), Decl(inferTypes1.ts, 65, 45))
+>b : Symbol(b, Decl(inferTypes1.ts, 65, 36))
+>U : Symbol(U, Decl(inferTypes1.ts, 65, 33), Decl(inferTypes1.ts, 65, 45))
+>U : Symbol(U, Decl(inferTypes1.ts, 65, 33), Decl(inferTypes1.ts, 65, 45))
 
 type T40 = X2<{}>;  // never
->T40 : Symbol(T40, Decl(inferTypes1.ts, 57, 62))
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
+>T40 : Symbol(T40, Decl(inferTypes1.ts, 65, 62))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
 
 type T41 = X2<{ a: string }>;  // never
->T41 : Symbol(T41, Decl(inferTypes1.ts, 59, 18))
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 60, 15))
+>T41 : Symbol(T41, Decl(inferTypes1.ts, 67, 18))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 68, 15))
 
 type T42 = X2<{ a: string, b: string }>;  // string
->T42 : Symbol(T42, Decl(inferTypes1.ts, 60, 29))
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 61, 15))
->b : Symbol(b, Decl(inferTypes1.ts, 61, 26))
+>T42 : Symbol(T42, Decl(inferTypes1.ts, 68, 29))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 69, 15))
+>b : Symbol(b, Decl(inferTypes1.ts, 69, 26))
 
 type T43 = X2<{ a: number, b: string }>;  // string | number
->T43 : Symbol(T43, Decl(inferTypes1.ts, 61, 40))
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 62, 15))
->b : Symbol(b, Decl(inferTypes1.ts, 62, 26))
+>T43 : Symbol(T43, Decl(inferTypes1.ts, 69, 40))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 70, 15))
+>b : Symbol(b, Decl(inferTypes1.ts, 70, 26))
 
 type T44 = X2<{ a: number, b: string, c: boolean }>;  // string | number
->T44 : Symbol(T44, Decl(inferTypes1.ts, 62, 40))
->X2 : Symbol(X2, Decl(inferTypes1.ts, 55, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 63, 15))
->b : Symbol(b, Decl(inferTypes1.ts, 63, 26))
->c : Symbol(c, Decl(inferTypes1.ts, 63, 37))
+>T44 : Symbol(T44, Decl(inferTypes1.ts, 70, 40))
+>X2 : Symbol(X2, Decl(inferTypes1.ts, 63, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 71, 15))
+>b : Symbol(b, Decl(inferTypes1.ts, 71, 26))
+>c : Symbol(c, Decl(inferTypes1.ts, 71, 37))
 
 type X3<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
->T : Symbol(T, Decl(inferTypes1.ts, 65, 8))
->T : Symbol(T, Decl(inferTypes1.ts, 65, 8))
->a : Symbol(a, Decl(inferTypes1.ts, 65, 24))
->x : Symbol(x, Decl(inferTypes1.ts, 65, 29))
->U : Symbol(U, Decl(inferTypes1.ts, 65, 37), Decl(inferTypes1.ts, 65, 62))
->b : Symbol(b, Decl(inferTypes1.ts, 65, 49))
->x : Symbol(x, Decl(inferTypes1.ts, 65, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 65, 37), Decl(inferTypes1.ts, 65, 62))
->U : Symbol(U, Decl(inferTypes1.ts, 65, 37), Decl(inferTypes1.ts, 65, 62))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
+>T : Symbol(T, Decl(inferTypes1.ts, 73, 8))
+>T : Symbol(T, Decl(inferTypes1.ts, 73, 8))
+>a : Symbol(a, Decl(inferTypes1.ts, 73, 24))
+>x : Symbol(x, Decl(inferTypes1.ts, 73, 29))
+>U : Symbol(U, Decl(inferTypes1.ts, 73, 37), Decl(inferTypes1.ts, 73, 62))
+>b : Symbol(b, Decl(inferTypes1.ts, 73, 49))
+>x : Symbol(x, Decl(inferTypes1.ts, 73, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 73, 37), Decl(inferTypes1.ts, 73, 62))
+>U : Symbol(U, Decl(inferTypes1.ts, 73, 37), Decl(inferTypes1.ts, 73, 62))
 
 type T50 = X3<{}>;  // never
->T50 : Symbol(T50, Decl(inferTypes1.ts, 65, 88))
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
+>T50 : Symbol(T50, Decl(inferTypes1.ts, 73, 88))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
 
 type T51 = X3<{ a: (x: string) => void }>;  // never
->T51 : Symbol(T51, Decl(inferTypes1.ts, 67, 18))
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 68, 15))
->x : Symbol(x, Decl(inferTypes1.ts, 68, 20))
+>T51 : Symbol(T51, Decl(inferTypes1.ts, 75, 18))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 76, 15))
+>x : Symbol(x, Decl(inferTypes1.ts, 76, 20))
 
 type T52 = X3<{ a: (x: string) => void, b: (x: string) => void }>;  // string
->T52 : Symbol(T52, Decl(inferTypes1.ts, 68, 42))
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 69, 15))
->x : Symbol(x, Decl(inferTypes1.ts, 69, 20))
->b : Symbol(b, Decl(inferTypes1.ts, 69, 39))
->x : Symbol(x, Decl(inferTypes1.ts, 69, 44))
+>T52 : Symbol(T52, Decl(inferTypes1.ts, 76, 42))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 77, 15))
+>x : Symbol(x, Decl(inferTypes1.ts, 77, 20))
+>b : Symbol(b, Decl(inferTypes1.ts, 77, 39))
+>x : Symbol(x, Decl(inferTypes1.ts, 77, 44))
 
 type T53 = X3<{ a: (x: number) => void, b: (x: string) => void }>;  // never
->T53 : Symbol(T53, Decl(inferTypes1.ts, 69, 66))
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 70, 15))
->x : Symbol(x, Decl(inferTypes1.ts, 70, 20))
->b : Symbol(b, Decl(inferTypes1.ts, 70, 39))
->x : Symbol(x, Decl(inferTypes1.ts, 70, 44))
+>T53 : Symbol(T53, Decl(inferTypes1.ts, 77, 66))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 78, 15))
+>x : Symbol(x, Decl(inferTypes1.ts, 78, 20))
+>b : Symbol(b, Decl(inferTypes1.ts, 78, 39))
+>x : Symbol(x, Decl(inferTypes1.ts, 78, 44))
 
 type T54 = X3<{ a: (x: number) => void, b: () => void }>;  // number
->T54 : Symbol(T54, Decl(inferTypes1.ts, 70, 66))
->X3 : Symbol(X3, Decl(inferTypes1.ts, 63, 52))
->a : Symbol(a, Decl(inferTypes1.ts, 71, 15))
->x : Symbol(x, Decl(inferTypes1.ts, 71, 20))
->b : Symbol(b, Decl(inferTypes1.ts, 71, 39))
+>T54 : Symbol(T54, Decl(inferTypes1.ts, 78, 66))
+>X3 : Symbol(X3, Decl(inferTypes1.ts, 71, 52))
+>a : Symbol(a, Decl(inferTypes1.ts, 79, 15))
+>x : Symbol(x, Decl(inferTypes1.ts, 79, 20))
+>b : Symbol(b, Decl(inferTypes1.ts, 79, 39))
 
 type T60 = infer U;  // Error
->T60 : Symbol(T60, Decl(inferTypes1.ts, 71, 57))
->U : Symbol(U, Decl(inferTypes1.ts, 73, 16))
+>T60 : Symbol(T60, Decl(inferTypes1.ts, 79, 57))
+>U : Symbol(U, Decl(inferTypes1.ts, 81, 16))
 
 type T61<T> = infer A extends infer B ? infer C : infer D;  // Error
->T61 : Symbol(T61, Decl(inferTypes1.ts, 73, 19))
->T : Symbol(T, Decl(inferTypes1.ts, 74, 9))
->A : Symbol(A, Decl(inferTypes1.ts, 74, 19))
->B : Symbol(B, Decl(inferTypes1.ts, 74, 35))
->C : Symbol(C, Decl(inferTypes1.ts, 74, 45))
->D : Symbol(D, Decl(inferTypes1.ts, 74, 55))
+>T61 : Symbol(T61, Decl(inferTypes1.ts, 81, 19))
+>T : Symbol(T, Decl(inferTypes1.ts, 82, 9))
+>A : Symbol(A, Decl(inferTypes1.ts, 82, 19))
+>B : Symbol(B, Decl(inferTypes1.ts, 82, 35))
+>C : Symbol(C, Decl(inferTypes1.ts, 82, 45))
+>D : Symbol(D, Decl(inferTypes1.ts, 82, 55))
 
 type T62<T> = U extends (infer U)[] ? U : U;  // Error
->T62 : Symbol(T62, Decl(inferTypes1.ts, 74, 58))
->T : Symbol(T, Decl(inferTypes1.ts, 75, 9))
->U : Symbol(U, Decl(inferTypes1.ts, 75, 30))
->U : Symbol(U, Decl(inferTypes1.ts, 75, 30))
+>T62 : Symbol(T62, Decl(inferTypes1.ts, 82, 58))
+>T : Symbol(T, Decl(inferTypes1.ts, 83, 9))
+>U : Symbol(U, Decl(inferTypes1.ts, 83, 30))
+>U : Symbol(U, Decl(inferTypes1.ts, 83, 30))
 
 type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
->T63 : Symbol(T63, Decl(inferTypes1.ts, 75, 44))
->T : Symbol(T, Decl(inferTypes1.ts, 76, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 76, 9))
->A : Symbol(A, Decl(inferTypes1.ts, 76, 30))
->B : Symbol(B, Decl(inferTypes1.ts, 76, 46))
->C : Symbol(C, Decl(inferTypes1.ts, 76, 56))
->D : Symbol(D, Decl(inferTypes1.ts, 76, 66))
+>T63 : Symbol(T63, Decl(inferTypes1.ts, 83, 44))
+>T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
+>A : Symbol(A, Decl(inferTypes1.ts, 84, 30))
+>B : Symbol(B, Decl(inferTypes1.ts, 84, 46))
+>C : Symbol(C, Decl(inferTypes1.ts, 84, 56))
+>D : Symbol(D, Decl(inferTypes1.ts, 84, 66))
 
 type T70<T extends string> = { x: T };
->T70 : Symbol(T70, Decl(inferTypes1.ts, 76, 88))
->T : Symbol(T, Decl(inferTypes1.ts, 78, 9))
->x : Symbol(x, Decl(inferTypes1.ts, 78, 30))
->T : Symbol(T, Decl(inferTypes1.ts, 78, 9))
+>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
+>T : Symbol(T, Decl(inferTypes1.ts, 86, 9))
+>x : Symbol(x, Decl(inferTypes1.ts, 86, 30))
+>T : Symbol(T, Decl(inferTypes1.ts, 86, 9))
 
 type T71<T> = T extends T70<infer U> ? T70<U> : never;
->T71 : Symbol(T71, Decl(inferTypes1.ts, 78, 38))
->T : Symbol(T, Decl(inferTypes1.ts, 79, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 79, 9))
->T70 : Symbol(T70, Decl(inferTypes1.ts, 76, 88))
->U : Symbol(U, Decl(inferTypes1.ts, 79, 33))
->T70 : Symbol(T70, Decl(inferTypes1.ts, 76, 88))
->U : Symbol(U, Decl(inferTypes1.ts, 79, 33))
+>T71 : Symbol(T71, Decl(inferTypes1.ts, 86, 38))
+>T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
+>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
+>U : Symbol(U, Decl(inferTypes1.ts, 87, 33))
+>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
+>U : Symbol(U, Decl(inferTypes1.ts, 87, 33))
 
 type T72<T extends number> = { y: T };
->T72 : Symbol(T72, Decl(inferTypes1.ts, 79, 54))
->T : Symbol(T, Decl(inferTypes1.ts, 81, 9))
->y : Symbol(y, Decl(inferTypes1.ts, 81, 30))
->T : Symbol(T, Decl(inferTypes1.ts, 81, 9))
+>T72 : Symbol(T72, Decl(inferTypes1.ts, 87, 54))
+>T : Symbol(T, Decl(inferTypes1.ts, 89, 9))
+>y : Symbol(y, Decl(inferTypes1.ts, 89, 30))
+>T : Symbol(T, Decl(inferTypes1.ts, 89, 9))
 
 type T73<T> = T extends T72<infer U> ? T70<U> : never;  // Error
->T73 : Symbol(T73, Decl(inferTypes1.ts, 81, 38))
->T : Symbol(T, Decl(inferTypes1.ts, 82, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 82, 9))
->T72 : Symbol(T72, Decl(inferTypes1.ts, 79, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 82, 33))
->T70 : Symbol(T70, Decl(inferTypes1.ts, 76, 88))
->U : Symbol(U, Decl(inferTypes1.ts, 82, 33))
+>T73 : Symbol(T73, Decl(inferTypes1.ts, 89, 38))
+>T : Symbol(T, Decl(inferTypes1.ts, 90, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 90, 9))
+>T72 : Symbol(T72, Decl(inferTypes1.ts, 87, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 90, 33))
+>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
+>U : Symbol(U, Decl(inferTypes1.ts, 90, 33))
 
 type T74<T extends number, U extends string> = { x: T, y: U };
->T74 : Symbol(T74, Decl(inferTypes1.ts, 82, 54))
->T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
->U : Symbol(U, Decl(inferTypes1.ts, 84, 26))
->x : Symbol(x, Decl(inferTypes1.ts, 84, 48))
->T : Symbol(T, Decl(inferTypes1.ts, 84, 9))
->y : Symbol(y, Decl(inferTypes1.ts, 84, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 84, 26))
+>T74 : Symbol(T74, Decl(inferTypes1.ts, 90, 54))
+>T : Symbol(T, Decl(inferTypes1.ts, 92, 9))
+>U : Symbol(U, Decl(inferTypes1.ts, 92, 26))
+>x : Symbol(x, Decl(inferTypes1.ts, 92, 48))
+>T : Symbol(T, Decl(inferTypes1.ts, 92, 9))
+>y : Symbol(y, Decl(inferTypes1.ts, 92, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 92, 26))
 
 type T75<T> = T extends T74<infer U, infer U> ? T70<U> | T72<U> | T74<U, U> : never;
->T75 : Symbol(T75, Decl(inferTypes1.ts, 84, 62))
->T : Symbol(T, Decl(inferTypes1.ts, 85, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 85, 9))
->T74 : Symbol(T74, Decl(inferTypes1.ts, 82, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
->T70 : Symbol(T70, Decl(inferTypes1.ts, 76, 88))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
->T72 : Symbol(T72, Decl(inferTypes1.ts, 79, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
->T74 : Symbol(T74, Decl(inferTypes1.ts, 82, 54))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
->U : Symbol(U, Decl(inferTypes1.ts, 85, 33), Decl(inferTypes1.ts, 85, 42))
+>T75 : Symbol(T75, Decl(inferTypes1.ts, 92, 62))
+>T : Symbol(T, Decl(inferTypes1.ts, 93, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 93, 9))
+>T74 : Symbol(T74, Decl(inferTypes1.ts, 90, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+>T70 : Symbol(T70, Decl(inferTypes1.ts, 84, 88))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+>T72 : Symbol(T72, Decl(inferTypes1.ts, 87, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+>T74 : Symbol(T74, Decl(inferTypes1.ts, 90, 54))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
+>U : Symbol(U, Decl(inferTypes1.ts, 93, 33), Decl(inferTypes1.ts, 93, 42))
 
 type T76<T extends T[], U extends T> = { x: T };
->T76 : Symbol(T76, Decl(inferTypes1.ts, 85, 84))
->T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
->U : Symbol(U, Decl(inferTypes1.ts, 87, 23))
->T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
->x : Symbol(x, Decl(inferTypes1.ts, 87, 40))
->T : Symbol(T, Decl(inferTypes1.ts, 87, 9))
+>T76 : Symbol(T76, Decl(inferTypes1.ts, 93, 84))
+>T : Symbol(T, Decl(inferTypes1.ts, 95, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 95, 9))
+>U : Symbol(U, Decl(inferTypes1.ts, 95, 23))
+>T : Symbol(T, Decl(inferTypes1.ts, 95, 9))
+>x : Symbol(x, Decl(inferTypes1.ts, 95, 40))
+>T : Symbol(T, Decl(inferTypes1.ts, 95, 9))
 
 type T77<T> = T extends T76<infer X, infer Y> ? T76<X, Y> : never;
->T77 : Symbol(T77, Decl(inferTypes1.ts, 87, 48))
->T : Symbol(T, Decl(inferTypes1.ts, 88, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 88, 9))
->T76 : Symbol(T76, Decl(inferTypes1.ts, 85, 84))
->X : Symbol(X, Decl(inferTypes1.ts, 88, 33))
->Y : Symbol(Y, Decl(inferTypes1.ts, 88, 42))
->T76 : Symbol(T76, Decl(inferTypes1.ts, 85, 84))
->X : Symbol(X, Decl(inferTypes1.ts, 88, 33))
->Y : Symbol(Y, Decl(inferTypes1.ts, 88, 42))
+>T77 : Symbol(T77, Decl(inferTypes1.ts, 95, 48))
+>T : Symbol(T, Decl(inferTypes1.ts, 96, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 96, 9))
+>T76 : Symbol(T76, Decl(inferTypes1.ts, 93, 84))
+>X : Symbol(X, Decl(inferTypes1.ts, 96, 33))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 96, 42))
+>T76 : Symbol(T76, Decl(inferTypes1.ts, 93, 84))
+>X : Symbol(X, Decl(inferTypes1.ts, 96, 33))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 96, 42))
 
 type T78<T> = T extends T76<infer X, infer X> ? T76<X, X> : never;
->T78 : Symbol(T78, Decl(inferTypes1.ts, 88, 66))
->T : Symbol(T, Decl(inferTypes1.ts, 89, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 89, 9))
->T76 : Symbol(T76, Decl(inferTypes1.ts, 85, 84))
->X : Symbol(X, Decl(inferTypes1.ts, 89, 33), Decl(inferTypes1.ts, 89, 42))
->X : Symbol(X, Decl(inferTypes1.ts, 89, 33), Decl(inferTypes1.ts, 89, 42))
->T76 : Symbol(T76, Decl(inferTypes1.ts, 85, 84))
->X : Symbol(X, Decl(inferTypes1.ts, 89, 33), Decl(inferTypes1.ts, 89, 42))
->X : Symbol(X, Decl(inferTypes1.ts, 89, 33), Decl(inferTypes1.ts, 89, 42))
+>T78 : Symbol(T78, Decl(inferTypes1.ts, 96, 66))
+>T : Symbol(T, Decl(inferTypes1.ts, 97, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 97, 9))
+>T76 : Symbol(T76, Decl(inferTypes1.ts, 93, 84))
+>X : Symbol(X, Decl(inferTypes1.ts, 97, 33), Decl(inferTypes1.ts, 97, 42))
+>X : Symbol(X, Decl(inferTypes1.ts, 97, 33), Decl(inferTypes1.ts, 97, 42))
+>T76 : Symbol(T76, Decl(inferTypes1.ts, 93, 84))
+>X : Symbol(X, Decl(inferTypes1.ts, 97, 33), Decl(inferTypes1.ts, 97, 42))
+>X : Symbol(X, Decl(inferTypes1.ts, 97, 33), Decl(inferTypes1.ts, 97, 42))
 
 type Foo<T extends string, U extends T> = [T, U];
->Foo : Symbol(Foo, Decl(inferTypes1.ts, 89, 66))
->T : Symbol(T, Decl(inferTypes1.ts, 91, 9))
->U : Symbol(U, Decl(inferTypes1.ts, 91, 26))
->T : Symbol(T, Decl(inferTypes1.ts, 91, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 91, 9))
->U : Symbol(U, Decl(inferTypes1.ts, 91, 26))
+>Foo : Symbol(Foo, Decl(inferTypes1.ts, 97, 66))
+>T : Symbol(T, Decl(inferTypes1.ts, 99, 9))
+>U : Symbol(U, Decl(inferTypes1.ts, 99, 26))
+>T : Symbol(T, Decl(inferTypes1.ts, 99, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 99, 9))
+>U : Symbol(U, Decl(inferTypes1.ts, 99, 26))
 
 type Bar<T> = T extends Foo<infer X, infer Y> ? Foo<X, Y> : never;
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
->T : Symbol(T, Decl(inferTypes1.ts, 92, 9))
->T : Symbol(T, Decl(inferTypes1.ts, 92, 9))
->Foo : Symbol(Foo, Decl(inferTypes1.ts, 89, 66))
->X : Symbol(X, Decl(inferTypes1.ts, 92, 33))
->Y : Symbol(Y, Decl(inferTypes1.ts, 92, 42))
->Foo : Symbol(Foo, Decl(inferTypes1.ts, 89, 66))
->X : Symbol(X, Decl(inferTypes1.ts, 92, 33))
->Y : Symbol(Y, Decl(inferTypes1.ts, 92, 42))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
+>T : Symbol(T, Decl(inferTypes1.ts, 100, 9))
+>T : Symbol(T, Decl(inferTypes1.ts, 100, 9))
+>Foo : Symbol(Foo, Decl(inferTypes1.ts, 97, 66))
+>X : Symbol(X, Decl(inferTypes1.ts, 100, 33))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 100, 42))
+>Foo : Symbol(Foo, Decl(inferTypes1.ts, 97, 66))
+>X : Symbol(X, Decl(inferTypes1.ts, 100, 33))
+>Y : Symbol(Y, Decl(inferTypes1.ts, 100, 42))
 
 type T90 = Bar<[string, string]>;  // [string, string]
->T90 : Symbol(T90, Decl(inferTypes1.ts, 92, 66))
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
+>T90 : Symbol(T90, Decl(inferTypes1.ts, 100, 66))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
 
 type T91 = Bar<[string, "a"]>;  // [string, "a"]
->T91 : Symbol(T91, Decl(inferTypes1.ts, 94, 33))
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
+>T91 : Symbol(T91, Decl(inferTypes1.ts, 102, 33))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
 
 type T92 = Bar<[string, "a"] & { x: string }>;  // [string, "a"]
->T92 : Symbol(T92, Decl(inferTypes1.ts, 95, 30))
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
->x : Symbol(x, Decl(inferTypes1.ts, 96, 32))
+>T92 : Symbol(T92, Decl(inferTypes1.ts, 103, 30))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
+>x : Symbol(x, Decl(inferTypes1.ts, 104, 32))
 
 type T93 = Bar<["a", string]>;  // never
->T93 : Symbol(T93, Decl(inferTypes1.ts, 96, 46))
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
+>T93 : Symbol(T93, Decl(inferTypes1.ts, 104, 46))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
 
 type T94 = Bar<[number, number]>;  // never
->T94 : Symbol(T94, Decl(inferTypes1.ts, 97, 30))
->Bar : Symbol(Bar, Decl(inferTypes1.ts, 91, 49))
+>T94 : Symbol(T94, Decl(inferTypes1.ts, 105, 30))
+>Bar : Symbol(Bar, Decl(inferTypes1.ts, 99, 49))
 
 // Example from #21496
 
 type JsonifiedObject<T extends object> = { [K in keyof T]: Jsonified<T[K]> };
->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 98, 33))
->T : Symbol(T, Decl(inferTypes1.ts, 102, 21))
->K : Symbol(K, Decl(inferTypes1.ts, 102, 44))
->T : Symbol(T, Decl(inferTypes1.ts, 102, 21))
->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 102, 77))
->T : Symbol(T, Decl(inferTypes1.ts, 102, 21))
->K : Symbol(K, Decl(inferTypes1.ts, 102, 44))
+>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 106, 33))
+>T : Symbol(T, Decl(inferTypes1.ts, 110, 21))
+>K : Symbol(K, Decl(inferTypes1.ts, 110, 44))
+>T : Symbol(T, Decl(inferTypes1.ts, 110, 21))
+>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 110, 77))
+>T : Symbol(T, Decl(inferTypes1.ts, 110, 21))
+>K : Symbol(K, Decl(inferTypes1.ts, 110, 44))
 
 type Jsonified<T> =
->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 102, 77))
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
+>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 110, 77))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
 
     T extends string | number | boolean | null ? T
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
 
     : T extends undefined | Function ? never // undefined and functions are removed
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
 >Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
 
     : T extends { toJSON(): infer R } ? R // toJSON is called if it exists (e.g. Date)
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
->toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 107, 17))
->R : Symbol(R, Decl(inferTypes1.ts, 107, 33))
->R : Symbol(R, Decl(inferTypes1.ts, 107, 33))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
+>toJSON : Symbol(toJSON, Decl(inferTypes1.ts, 115, 17))
+>R : Symbol(R, Decl(inferTypes1.ts, 115, 33))
+>R : Symbol(R, Decl(inferTypes1.ts, 115, 33))
 
     : T extends object ? JsonifiedObject<T>
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
->JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 98, 33))
->T : Symbol(T, Decl(inferTypes1.ts, 104, 15))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
+>JsonifiedObject : Symbol(JsonifiedObject, Decl(inferTypes1.ts, 106, 33))
+>T : Symbol(T, Decl(inferTypes1.ts, 112, 15))
 
     : "what is this";
 
 type Example = {
->Example : Symbol(Example, Decl(inferTypes1.ts, 109, 21))
+>Example : Symbol(Example, Decl(inferTypes1.ts, 117, 21))
 
     str: "literalstring",
->str : Symbol(str, Decl(inferTypes1.ts, 111, 16))
+>str : Symbol(str, Decl(inferTypes1.ts, 119, 16))
 
     fn: () => void,
->fn : Symbol(fn, Decl(inferTypes1.ts, 112, 25))
+>fn : Symbol(fn, Decl(inferTypes1.ts, 120, 25))
 
     date: Date,
->date : Symbol(date, Decl(inferTypes1.ts, 113, 19))
+>date : Symbol(date, Decl(inferTypes1.ts, 121, 19))
 >Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
 
     customClass: MyClass,
->customClass : Symbol(customClass, Decl(inferTypes1.ts, 114, 15))
->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 121, 1))
+>customClass : Symbol(customClass, Decl(inferTypes1.ts, 122, 15))
+>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 129, 1))
 
     obj: {
->obj : Symbol(obj, Decl(inferTypes1.ts, 115, 25))
+>obj : Symbol(obj, Decl(inferTypes1.ts, 123, 25))
 
         prop: "property",
->prop : Symbol(prop, Decl(inferTypes1.ts, 116, 10))
+>prop : Symbol(prop, Decl(inferTypes1.ts, 124, 10))
 
         clz: MyClass,
->clz : Symbol(clz, Decl(inferTypes1.ts, 117, 25))
->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 121, 1))
+>clz : Symbol(clz, Decl(inferTypes1.ts, 125, 25))
+>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 129, 1))
 
         nested: { attr: Date }
->nested : Symbol(nested, Decl(inferTypes1.ts, 118, 21))
->attr : Symbol(attr, Decl(inferTypes1.ts, 119, 17))
+>nested : Symbol(nested, Decl(inferTypes1.ts, 126, 21))
+>attr : Symbol(attr, Decl(inferTypes1.ts, 127, 17))
 >Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --))
 
     },
 }
 
 declare class MyClass {
->MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 121, 1))
+>MyClass : Symbol(MyClass, Decl(inferTypes1.ts, 129, 1))
 
     toJSON(): "correct";
->toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 123, 23))
+>toJSON : Symbol(MyClass.toJSON, Decl(inferTypes1.ts, 131, 23))
 }
 
 type JsonifiedExample = Jsonified<Example>;
->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 125, 1))
->Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 102, 77))
->Example : Symbol(Example, Decl(inferTypes1.ts, 109, 21))
+>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 133, 1))
+>Jsonified : Symbol(Jsonified, Decl(inferTypes1.ts, 110, 77))
+>Example : Symbol(Example, Decl(inferTypes1.ts, 117, 21))
 
 declare let ex: JsonifiedExample;
->ex : Symbol(ex, Decl(inferTypes1.ts, 128, 11))
->JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 125, 1))
+>ex : Symbol(ex, Decl(inferTypes1.ts, 136, 11))
+>JsonifiedExample : Symbol(JsonifiedExample, Decl(inferTypes1.ts, 133, 1))
 
 const z1: "correct" = ex.customClass;
->z1 : Symbol(z1, Decl(inferTypes1.ts, 129, 5))
->ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 114, 15))
->ex : Symbol(ex, Decl(inferTypes1.ts, 128, 11))
->customClass : Symbol(customClass, Decl(inferTypes1.ts, 114, 15))
+>z1 : Symbol(z1, Decl(inferTypes1.ts, 137, 5))
+>ex.customClass : Symbol(customClass, Decl(inferTypes1.ts, 122, 15))
+>ex : Symbol(ex, Decl(inferTypes1.ts, 136, 11))
+>customClass : Symbol(customClass, Decl(inferTypes1.ts, 122, 15))
 
 const z2: string = ex.obj.nested.attr;
->z2 : Symbol(z2, Decl(inferTypes1.ts, 130, 5))
->ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 119, 17))
->ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 118, 21))
->ex.obj : Symbol(obj, Decl(inferTypes1.ts, 115, 25))
->ex : Symbol(ex, Decl(inferTypes1.ts, 128, 11))
->obj : Symbol(obj, Decl(inferTypes1.ts, 115, 25))
->nested : Symbol(nested, Decl(inferTypes1.ts, 118, 21))
->attr : Symbol(attr, Decl(inferTypes1.ts, 119, 17))
+>z2 : Symbol(z2, Decl(inferTypes1.ts, 138, 5))
+>ex.obj.nested.attr : Symbol(attr, Decl(inferTypes1.ts, 127, 17))
+>ex.obj.nested : Symbol(nested, Decl(inferTypes1.ts, 126, 21))
+>ex.obj : Symbol(obj, Decl(inferTypes1.ts, 123, 25))
+>ex : Symbol(ex, Decl(inferTypes1.ts, 136, 11))
+>obj : Symbol(obj, Decl(inferTypes1.ts, 123, 25))
+>nested : Symbol(nested, Decl(inferTypes1.ts, 126, 21))
+>attr : Symbol(attr, Decl(inferTypes1.ts, 127, 17))
 
 // Repros from #21631
 
 type A1<T, U extends A1<any, any>> = [T, U];
->A1 : Symbol(A1, Decl(inferTypes1.ts, 130, 38))
->T : Symbol(T, Decl(inferTypes1.ts, 134, 8))
->U : Symbol(U, Decl(inferTypes1.ts, 134, 10))
->A1 : Symbol(A1, Decl(inferTypes1.ts, 130, 38))
->T : Symbol(T, Decl(inferTypes1.ts, 134, 8))
->U : Symbol(U, Decl(inferTypes1.ts, 134, 10))
+>A1 : Symbol(A1, Decl(inferTypes1.ts, 138, 38))
+>T : Symbol(T, Decl(inferTypes1.ts, 142, 8))
+>U : Symbol(U, Decl(inferTypes1.ts, 142, 10))
+>A1 : Symbol(A1, Decl(inferTypes1.ts, 138, 38))
+>T : Symbol(T, Decl(inferTypes1.ts, 142, 8))
+>U : Symbol(U, Decl(inferTypes1.ts, 142, 10))
 
 type B1<S> = S extends A1<infer T, infer U> ? [T, U] : never;
->B1 : Symbol(B1, Decl(inferTypes1.ts, 134, 44))
->S : Symbol(S, Decl(inferTypes1.ts, 135, 8))
->S : Symbol(S, Decl(inferTypes1.ts, 135, 8))
->A1 : Symbol(A1, Decl(inferTypes1.ts, 130, 38))
->T : Symbol(T, Decl(inferTypes1.ts, 135, 31))
->U : Symbol(U, Decl(inferTypes1.ts, 135, 40))
->T : Symbol(T, Decl(inferTypes1.ts, 135, 31))
->U : Symbol(U, Decl(inferTypes1.ts, 135, 40))
+>B1 : Symbol(B1, Decl(inferTypes1.ts, 142, 44))
+>S : Symbol(S, Decl(inferTypes1.ts, 143, 8))
+>S : Symbol(S, Decl(inferTypes1.ts, 143, 8))
+>A1 : Symbol(A1, Decl(inferTypes1.ts, 138, 38))
+>T : Symbol(T, Decl(inferTypes1.ts, 143, 31))
+>U : Symbol(U, Decl(inferTypes1.ts, 143, 40))
+>T : Symbol(T, Decl(inferTypes1.ts, 143, 31))
+>U : Symbol(U, Decl(inferTypes1.ts, 143, 40))
 
 type A2<T, U extends void> = [T, U];
->A2 : Symbol(A2, Decl(inferTypes1.ts, 135, 61))
->T : Symbol(T, Decl(inferTypes1.ts, 137, 8))
->U : Symbol(U, Decl(inferTypes1.ts, 137, 10))
->T : Symbol(T, Decl(inferTypes1.ts, 137, 8))
->U : Symbol(U, Decl(inferTypes1.ts, 137, 10))
+>A2 : Symbol(A2, Decl(inferTypes1.ts, 143, 61))
+>T : Symbol(T, Decl(inferTypes1.ts, 145, 8))
+>U : Symbol(U, Decl(inferTypes1.ts, 145, 10))
+>T : Symbol(T, Decl(inferTypes1.ts, 145, 8))
+>U : Symbol(U, Decl(inferTypes1.ts, 145, 10))
 
 type B2<S> = S extends A2<infer T, infer U> ? [T, U] : never;
->B2 : Symbol(B2, Decl(inferTypes1.ts, 137, 36))
->S : Symbol(S, Decl(inferTypes1.ts, 138, 8))
->S : Symbol(S, Decl(inferTypes1.ts, 138, 8))
->A2 : Symbol(A2, Decl(inferTypes1.ts, 135, 61))
->T : Symbol(T, Decl(inferTypes1.ts, 138, 31))
->U : Symbol(U, Decl(inferTypes1.ts, 138, 40))
->T : Symbol(T, Decl(inferTypes1.ts, 138, 31))
->U : Symbol(U, Decl(inferTypes1.ts, 138, 40))
+>B2 : Symbol(B2, Decl(inferTypes1.ts, 145, 36))
+>S : Symbol(S, Decl(inferTypes1.ts, 146, 8))
+>S : Symbol(S, Decl(inferTypes1.ts, 146, 8))
+>A2 : Symbol(A2, Decl(inferTypes1.ts, 143, 61))
+>T : Symbol(T, Decl(inferTypes1.ts, 146, 31))
+>U : Symbol(U, Decl(inferTypes1.ts, 146, 40))
+>T : Symbol(T, Decl(inferTypes1.ts, 146, 31))
+>U : Symbol(U, Decl(inferTypes1.ts, 146, 40))
 
 type C2<S, U extends void> = S extends A2<infer T, U> ? [T, U] : never;
->C2 : Symbol(C2, Decl(inferTypes1.ts, 138, 61))
->S : Symbol(S, Decl(inferTypes1.ts, 139, 8))
->U : Symbol(U, Decl(inferTypes1.ts, 139, 10))
->S : Symbol(S, Decl(inferTypes1.ts, 139, 8))
->A2 : Symbol(A2, Decl(inferTypes1.ts, 135, 61))
->T : Symbol(T, Decl(inferTypes1.ts, 139, 47))
->U : Symbol(U, Decl(inferTypes1.ts, 139, 10))
->T : Symbol(T, Decl(inferTypes1.ts, 139, 47))
->U : Symbol(U, Decl(inferTypes1.ts, 139, 10))
+>C2 : Symbol(C2, Decl(inferTypes1.ts, 146, 61))
+>S : Symbol(S, Decl(inferTypes1.ts, 147, 8))
+>U : Symbol(U, Decl(inferTypes1.ts, 147, 10))
+>S : Symbol(S, Decl(inferTypes1.ts, 147, 8))
+>A2 : Symbol(A2, Decl(inferTypes1.ts, 143, 61))
+>T : Symbol(T, Decl(inferTypes1.ts, 147, 47))
+>U : Symbol(U, Decl(inferTypes1.ts, 147, 10))
+>T : Symbol(T, Decl(inferTypes1.ts, 147, 47))
+>U : Symbol(U, Decl(inferTypes1.ts, 147, 10))
 
 // Repro from #21735
 
 type A<T> = T extends string ? { [P in T]: void; } : T;
->A : Symbol(A, Decl(inferTypes1.ts, 139, 71))
->T : Symbol(T, Decl(inferTypes1.ts, 143, 7))
->T : Symbol(T, Decl(inferTypes1.ts, 143, 7))
->P : Symbol(P, Decl(inferTypes1.ts, 143, 34))
->T : Symbol(T, Decl(inferTypes1.ts, 143, 7))
->T : Symbol(T, Decl(inferTypes1.ts, 143, 7))
+>A : Symbol(A, Decl(inferTypes1.ts, 147, 71))
+>T : Symbol(T, Decl(inferTypes1.ts, 151, 7))
+>T : Symbol(T, Decl(inferTypes1.ts, 151, 7))
+>P : Symbol(P, Decl(inferTypes1.ts, 151, 34))
+>T : Symbol(T, Decl(inferTypes1.ts, 151, 7))
+>T : Symbol(T, Decl(inferTypes1.ts, 151, 7))
 
 type B<T> = string extends T ? { [P in T]: void; } : T;  // Error
->B : Symbol(B, Decl(inferTypes1.ts, 143, 55))
->T : Symbol(T, Decl(inferTypes1.ts, 144, 7))
->T : Symbol(T, Decl(inferTypes1.ts, 144, 7))
->P : Symbol(P, Decl(inferTypes1.ts, 144, 34))
->T : Symbol(T, Decl(inferTypes1.ts, 144, 7))
->T : Symbol(T, Decl(inferTypes1.ts, 144, 7))
+>B : Symbol(B, Decl(inferTypes1.ts, 151, 55))
+>T : Symbol(T, Decl(inferTypes1.ts, 152, 7))
+>T : Symbol(T, Decl(inferTypes1.ts, 152, 7))
+>P : Symbol(P, Decl(inferTypes1.ts, 152, 34))
+>T : Symbol(T, Decl(inferTypes1.ts, 152, 7))
+>T : Symbol(T, Decl(inferTypes1.ts, 152, 7))
 
 // Repro from #22302
 
 type MatchingKeys<T, U, K extends keyof T = keyof T> =
->MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 144, 55))
->T : Symbol(T, Decl(inferTypes1.ts, 148, 18))
->U : Symbol(U, Decl(inferTypes1.ts, 148, 20))
->K : Symbol(K, Decl(inferTypes1.ts, 148, 23))
->T : Symbol(T, Decl(inferTypes1.ts, 148, 18))
->T : Symbol(T, Decl(inferTypes1.ts, 148, 18))
+>MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 152, 55))
+>T : Symbol(T, Decl(inferTypes1.ts, 156, 18))
+>U : Symbol(U, Decl(inferTypes1.ts, 156, 20))
+>K : Symbol(K, Decl(inferTypes1.ts, 156, 23))
+>T : Symbol(T, Decl(inferTypes1.ts, 156, 18))
+>T : Symbol(T, Decl(inferTypes1.ts, 156, 18))
 
     K extends keyof T ? T[K] extends U ? K : never : never;
->K : Symbol(K, Decl(inferTypes1.ts, 148, 23))
->T : Symbol(T, Decl(inferTypes1.ts, 148, 18))
->T : Symbol(T, Decl(inferTypes1.ts, 148, 18))
->K : Symbol(K, Decl(inferTypes1.ts, 148, 23))
->U : Symbol(U, Decl(inferTypes1.ts, 148, 20))
->K : Symbol(K, Decl(inferTypes1.ts, 148, 23))
+>K : Symbol(K, Decl(inferTypes1.ts, 156, 23))
+>T : Symbol(T, Decl(inferTypes1.ts, 156, 18))
+>T : Symbol(T, Decl(inferTypes1.ts, 156, 18))
+>K : Symbol(K, Decl(inferTypes1.ts, 156, 23))
+>U : Symbol(U, Decl(inferTypes1.ts, 156, 20))
+>K : Symbol(K, Decl(inferTypes1.ts, 156, 23))
 
 type VoidKeys<T> = MatchingKeys<T, void>;
->VoidKeys : Symbol(VoidKeys, Decl(inferTypes1.ts, 149, 59))
->T : Symbol(T, Decl(inferTypes1.ts, 151, 14))
->MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 144, 55))
->T : Symbol(T, Decl(inferTypes1.ts, 151, 14))
+>VoidKeys : Symbol(VoidKeys, Decl(inferTypes1.ts, 157, 59))
+>T : Symbol(T, Decl(inferTypes1.ts, 159, 14))
+>MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 152, 55))
+>T : Symbol(T, Decl(inferTypes1.ts, 159, 14))
 
 interface test {
->test : Symbol(test, Decl(inferTypes1.ts, 151, 41))
+>test : Symbol(test, Decl(inferTypes1.ts, 159, 41))
 
     a: 1,
->a : Symbol(test.a, Decl(inferTypes1.ts, 153, 16))
+>a : Symbol(test.a, Decl(inferTypes1.ts, 161, 16))
 
     b: void
->b : Symbol(test.b, Decl(inferTypes1.ts, 154, 9))
+>b : Symbol(test.b, Decl(inferTypes1.ts, 162, 9))
 }
 
 type T80 = MatchingKeys<test, void>;
->T80 : Symbol(T80, Decl(inferTypes1.ts, 156, 1))
->MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 144, 55))
->test : Symbol(test, Decl(inferTypes1.ts, 151, 41))
+>T80 : Symbol(T80, Decl(inferTypes1.ts, 164, 1))
+>MatchingKeys : Symbol(MatchingKeys, Decl(inferTypes1.ts, 152, 55))
+>test : Symbol(test, Decl(inferTypes1.ts, 159, 41))
 
 type T81 = VoidKeys<test>;
->T81 : Symbol(T81, Decl(inferTypes1.ts, 158, 36))
->VoidKeys : Symbol(VoidKeys, Decl(inferTypes1.ts, 149, 59))
->test : Symbol(test, Decl(inferTypes1.ts, 151, 41))
+>T81 : Symbol(T81, Decl(inferTypes1.ts, 166, 36))
+>VoidKeys : Symbol(VoidKeys, Decl(inferTypes1.ts, 157, 59))
+>test : Symbol(test, Decl(inferTypes1.ts, 159, 41))
 
 // Repro from #22221
 
 type MustBeString<T extends string> = T;
->MustBeString : Symbol(MustBeString, Decl(inferTypes1.ts, 159, 26))
->T : Symbol(T, Decl(inferTypes1.ts, 163, 18))
->T : Symbol(T, Decl(inferTypes1.ts, 163, 18))
+>MustBeString : Symbol(MustBeString, Decl(inferTypes1.ts, 167, 26))
+>T : Symbol(T, Decl(inferTypes1.ts, 171, 18))
+>T : Symbol(T, Decl(inferTypes1.ts, 171, 18))
 
 type EnsureIsString<T> = T extends MustBeString<infer U> ? U : never;
->EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 163, 40))
->T : Symbol(T, Decl(inferTypes1.ts, 164, 20))
->T : Symbol(T, Decl(inferTypes1.ts, 164, 20))
->MustBeString : Symbol(MustBeString, Decl(inferTypes1.ts, 159, 26))
->U : Symbol(U, Decl(inferTypes1.ts, 164, 53))
->U : Symbol(U, Decl(inferTypes1.ts, 164, 53))
+>EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 171, 40))
+>T : Symbol(T, Decl(inferTypes1.ts, 172, 20))
+>T : Symbol(T, Decl(inferTypes1.ts, 172, 20))
+>MustBeString : Symbol(MustBeString, Decl(inferTypes1.ts, 167, 26))
+>U : Symbol(U, Decl(inferTypes1.ts, 172, 53))
+>U : Symbol(U, Decl(inferTypes1.ts, 172, 53))
 
 type Test1 = EnsureIsString<"hello">;  // "hello"
->Test1 : Symbol(Test1, Decl(inferTypes1.ts, 164, 69))
->EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 163, 40))
+>Test1 : Symbol(Test1, Decl(inferTypes1.ts, 172, 69))
+>EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 171, 40))
 
 type Test2 = EnsureIsString<42>;  // never
->Test2 : Symbol(Test2, Decl(inferTypes1.ts, 166, 37))
->EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 163, 40))
+>Test2 : Symbol(Test2, Decl(inferTypes1.ts, 174, 37))
+>EnsureIsString : Symbol(EnsureIsString, Decl(inferTypes1.ts, 171, 40))
 
 // Repros from #26856
 
 function invoker <K extends string | number | symbol, A extends any[]> (key: K, ...args: A) {
->invoker : Symbol(invoker, Decl(inferTypes1.ts, 167, 32))
->K : Symbol(K, Decl(inferTypes1.ts, 171, 18))
->A : Symbol(A, Decl(inferTypes1.ts, 171, 53))
->key : Symbol(key, Decl(inferTypes1.ts, 171, 72))
->K : Symbol(K, Decl(inferTypes1.ts, 171, 18))
->args : Symbol(args, Decl(inferTypes1.ts, 171, 79))
->A : Symbol(A, Decl(inferTypes1.ts, 171, 53))
+>invoker : Symbol(invoker, Decl(inferTypes1.ts, 175, 32))
+>K : Symbol(K, Decl(inferTypes1.ts, 179, 18))
+>A : Symbol(A, Decl(inferTypes1.ts, 179, 53))
+>key : Symbol(key, Decl(inferTypes1.ts, 179, 72))
+>K : Symbol(K, Decl(inferTypes1.ts, 179, 18))
+>args : Symbol(args, Decl(inferTypes1.ts, 179, 79))
+>A : Symbol(A, Decl(inferTypes1.ts, 179, 53))
 
     return <T extends Record<K, (...args: A) => any>> (obj: T): ReturnType<T[K]> => obj[key](...args)
->T : Symbol(T, Decl(inferTypes1.ts, 172, 12))
+>T : Symbol(T, Decl(inferTypes1.ts, 180, 12))
 >Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
->K : Symbol(K, Decl(inferTypes1.ts, 171, 18))
->args : Symbol(args, Decl(inferTypes1.ts, 172, 33))
->A : Symbol(A, Decl(inferTypes1.ts, 171, 53))
->obj : Symbol(obj, Decl(inferTypes1.ts, 172, 55))
->T : Symbol(T, Decl(inferTypes1.ts, 172, 12))
+>K : Symbol(K, Decl(inferTypes1.ts, 179, 18))
+>args : Symbol(args, Decl(inferTypes1.ts, 180, 33))
+>A : Symbol(A, Decl(inferTypes1.ts, 179, 53))
+>obj : Symbol(obj, Decl(inferTypes1.ts, 180, 55))
+>T : Symbol(T, Decl(inferTypes1.ts, 180, 12))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->T : Symbol(T, Decl(inferTypes1.ts, 172, 12))
->K : Symbol(K, Decl(inferTypes1.ts, 171, 18))
->obj : Symbol(obj, Decl(inferTypes1.ts, 172, 55))
->key : Symbol(key, Decl(inferTypes1.ts, 171, 72))
->args : Symbol(args, Decl(inferTypes1.ts, 171, 79))
+>T : Symbol(T, Decl(inferTypes1.ts, 180, 12))
+>K : Symbol(K, Decl(inferTypes1.ts, 179, 18))
+>obj : Symbol(obj, Decl(inferTypes1.ts, 180, 55))
+>key : Symbol(key, Decl(inferTypes1.ts, 179, 72))
+>args : Symbol(args, Decl(inferTypes1.ts, 179, 79))
 }
 
 const result = invoker('test', true)({ test: (a: boolean) => 123 })
->result : Symbol(result, Decl(inferTypes1.ts, 175, 5))
->invoker : Symbol(invoker, Decl(inferTypes1.ts, 167, 32))
->test : Symbol(test, Decl(inferTypes1.ts, 175, 38))
->a : Symbol(a, Decl(inferTypes1.ts, 175, 46))
+>result : Symbol(result, Decl(inferTypes1.ts, 183, 5))
+>invoker : Symbol(invoker, Decl(inferTypes1.ts, 175, 32))
+>test : Symbol(test, Decl(inferTypes1.ts, 183, 38))
+>a : Symbol(a, Decl(inferTypes1.ts, 183, 46))
 
 type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
->Foo2 : Symbol(Foo2, Decl(inferTypes1.ts, 175, 67))
->A : Symbol(A, Decl(inferTypes1.ts, 177, 10))
+>Foo2 : Symbol(Foo2, Decl(inferTypes1.ts, 183, 67))
+>A : Symbol(A, Decl(inferTypes1.ts, 185, 10))
 >ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --))
->args : Symbol(args, Decl(inferTypes1.ts, 177, 41))
->A : Symbol(A, Decl(inferTypes1.ts, 177, 10))
+>args : Symbol(args, Decl(inferTypes1.ts, 185, 41))
+>A : Symbol(A, Decl(inferTypes1.ts, 185, 10))
 
diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types
index aa421dd4c4d76..fec5a699c57d0 100644
--- a/tests/baselines/reference/inferTypes1.types
+++ b/tests/baselines/reference/inferTypes1.types
@@ -54,6 +54,18 @@ class C {
 >0 : 0
 }
 
+abstract class Abstract {
+>Abstract : Abstract
+
+    x = 0;
+>x : number
+>0 : 0
+
+    y = 0;
+>y : number
+>0 : 0
+}
+
 type T10 = ReturnType<() => string>;  // string
 >T10 : string
 
@@ -104,6 +116,20 @@ type U13 = InstanceType<string>;  // Error
 type U14 = InstanceType<Function>;  // Error
 >U14 : any
 
+type U15 = InstanceType<typeof Abstract>;  // Abstract
+>U15 : Abstract
+>Abstract : typeof Abstract
+
+type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
+>U16 : T[]
+>x : string
+>args : T
+
+type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
+>U17 : T[]
+>x : string
+>args : T
+
 type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
 >ArgumentType : ArgumentType<T>
 >x : any
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.errors.txt b/tests/baselines/reference/mixinAbstractClasses.2.errors.txt
new file mode 100644
index 0000000000000..d009651f6ce3d
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.2.errors.txt
@@ -0,0 +1,33 @@
+tests/cases/conformance/classes/mixinAbstractClasses.2.ts(20,7): error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+tests/cases/conformance/classes/mixinAbstractClasses.2.ts(24,1): error TS2511: Cannot create an instance of an abstract class.
+
+
+==== tests/cases/conformance/classes/mixinAbstractClasses.2.ts (2 errors) ====
+    interface Mixin {
+        mixinMethod(): void;
+    }
+    
+    function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+        abstract class MixinClass extends baseClass implements Mixin {
+            mixinMethod() {
+            }
+        }
+        return MixinClass;
+    }
+    
+    abstract class AbstractBase {
+        abstract abstractBaseMethod(): void;
+    }
+    
+    const MixedBase = Mixin(AbstractBase);
+    
+    // error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+    class DerivedFromAbstract extends MixedBase {
+          ~~~~~~~~~~~~~~~~~~~
+!!! error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+    }
+    
+    // error expected: Cannot create an instance of an abstract class.
+    new MixedBase();
+    ~~~~~~~~~~~~~~~
+!!! error TS2511: Cannot create an instance of an abstract class.
\ No newline at end of file
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.js b/tests/baselines/reference/mixinAbstractClasses.2.js
new file mode 100644
index 0000000000000..8f1a4a5d9d928
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.2.js
@@ -0,0 +1,55 @@
+//// [mixinAbstractClasses.2.ts]
+interface Mixin {
+    mixinMethod(): void;
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+    abstract class MixinClass extends baseClass implements Mixin {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+const MixedBase = Mixin(AbstractBase);
+
+// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+class DerivedFromAbstract extends MixedBase {
+}
+
+// error expected: Cannot create an instance of an abstract class.
+new MixedBase();
+
+//// [mixinAbstractClasses.2.js]
+function Mixin(baseClass) {
+    class MixinClass extends baseClass {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+class AbstractBase {
+}
+const MixedBase = Mixin(AbstractBase);
+// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+class DerivedFromAbstract extends MixedBase {
+}
+// error expected: Cannot create an instance of an abstract class.
+new MixedBase();
+
+
+//// [mixinAbstractClasses.2.d.ts]
+interface Mixin {
+    mixinMethod(): void;
+}
+declare function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin);
+declare abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+declare const MixedBase: typeof AbstractBase & (abstract new (...args: any) => Mixin);
+declare class DerivedFromAbstract extends MixedBase {
+}
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.symbols b/tests/baselines/reference/mixinAbstractClasses.2.symbols
new file mode 100644
index 0000000000000..b9de3f4654a64
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.2.symbols
@@ -0,0 +1,53 @@
+=== tests/cases/conformance/classes/mixinAbstractClasses.2.ts ===
+interface Mixin {
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
+
+    mixinMethod(): void;
+>mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.2.ts, 0, 17))
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.2.ts, 4, 15))
+>args : Symbol(args, Decl(mixinAbstractClasses.2.ts, 4, 48))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.2.ts, 4, 70))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.2.ts, 4, 15))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.2.ts, 4, 15))
+>args : Symbol(args, Decl(mixinAbstractClasses.2.ts, 4, 122))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
+
+    abstract class MixinClass extends baseClass implements Mixin {
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.2.ts, 4, 70))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
+
+        mixinMethod() {
+>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.2.ts, 5, 66))
+        }
+    }
+    return MixinClass;
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
+}
+
+abstract class AbstractBase {
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 12, 29))
+}
+
+const MixedBase = Mixin(AbstractBase);
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
+
+// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+class DerivedFromAbstract extends MixedBase {
+>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.2.ts, 16, 38))
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+}
+
+// error expected: Cannot create an instance of an abstract class.
+new MixedBase();
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.types b/tests/baselines/reference/mixinAbstractClasses.2.types
new file mode 100644
index 0000000000000..cde5f90e98a28
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.2.types
@@ -0,0 +1,48 @@
+=== tests/cases/conformance/classes/mixinAbstractClasses.2.ts ===
+interface Mixin {
+    mixinMethod(): void;
+>mixinMethod : () => void
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+>Mixin : <TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass) => TBaseClass & (abstract new (...args: any) => Mixin)
+>args : any
+>baseClass : TBaseClass
+>args : any
+
+    abstract class MixinClass extends baseClass implements Mixin {
+>MixinClass : MixinClass
+>baseClass : TBaseClass
+
+        mixinMethod() {
+>mixinMethod : () => void
+        }
+    }
+    return MixinClass;
+>MixinClass : { new (...args: any): MixinClass; prototype: Mixin<any>.MixinClass; } & TBaseClass
+}
+
+abstract class AbstractBase {
+>AbstractBase : AbstractBase
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : () => void
+}
+
+const MixedBase = Mixin(AbstractBase);
+>MixedBase : typeof AbstractBase & (abstract new (...args: any) => Mixin)
+>Mixin(AbstractBase) : typeof AbstractBase & (abstract new (...args: any) => Mixin)
+>Mixin : <TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass) => TBaseClass & (abstract new (...args: any) => Mixin)
+>AbstractBase : typeof AbstractBase
+
+// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+class DerivedFromAbstract extends MixedBase {
+>DerivedFromAbstract : DerivedFromAbstract
+>MixedBase : AbstractBase & Mixin
+}
+
+// error expected: Cannot create an instance of an abstract class.
+new MixedBase();
+>new MixedBase() : any
+>MixedBase : typeof AbstractBase & (abstract new (...args: any) => Mixin)
+
diff --git a/tests/baselines/reference/mixinAbstractClasses.js b/tests/baselines/reference/mixinAbstractClasses.js
new file mode 100644
index 0000000000000..3c887a087fbdc
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.js
@@ -0,0 +1,82 @@
+//// [mixinAbstractClasses.ts]
+interface Mixin {
+    mixinMethod(): void;
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+    abstract class MixinClass extends baseClass implements Mixin {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+
+class ConcreteBase {
+    baseMethod() {}
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+class DerivedFromConcrete extends Mixin(ConcreteBase) {
+}
+
+const wasConcrete = new DerivedFromConcrete();
+wasConcrete.baseMethod();
+wasConcrete.mixinMethod();
+
+class DerivedFromAbstract extends Mixin(AbstractBase) {
+    abstractBaseMethod() {}
+}
+
+const wasAbstract = new DerivedFromAbstract();
+wasAbstract.abstractBaseMethod();
+wasAbstract.mixinMethod();
+
+//// [mixinAbstractClasses.js]
+function Mixin(baseClass) {
+    class MixinClass extends baseClass {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+class ConcreteBase {
+    baseMethod() { }
+}
+class AbstractBase {
+}
+class DerivedFromConcrete extends Mixin(ConcreteBase) {
+}
+const wasConcrete = new DerivedFromConcrete();
+wasConcrete.baseMethod();
+wasConcrete.mixinMethod();
+class DerivedFromAbstract extends Mixin(AbstractBase) {
+    abstractBaseMethod() { }
+}
+const wasAbstract = new DerivedFromAbstract();
+wasAbstract.abstractBaseMethod();
+wasAbstract.mixinMethod();
+
+
+//// [mixinAbstractClasses.d.ts]
+interface Mixin {
+    mixinMethod(): void;
+}
+declare function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin);
+declare class ConcreteBase {
+    baseMethod(): void;
+}
+declare abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+declare const DerivedFromConcrete_base: typeof ConcreteBase & (abstract new (...args: any) => Mixin);
+declare class DerivedFromConcrete extends DerivedFromConcrete_base {
+}
+declare const wasConcrete: DerivedFromConcrete;
+declare const DerivedFromAbstract_base: typeof AbstractBase & (abstract new (...args: any) => Mixin);
+declare class DerivedFromAbstract extends DerivedFromAbstract_base {
+    abstractBaseMethod(): void;
+}
+declare const wasAbstract: DerivedFromAbstract;
diff --git a/tests/baselines/reference/mixinAbstractClasses.symbols b/tests/baselines/reference/mixinAbstractClasses.symbols
new file mode 100644
index 0000000000000..1c45de5e900ff
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.symbols
@@ -0,0 +1,88 @@
+=== tests/cases/conformance/classes/mixinAbstractClasses.ts ===
+interface Mixin {
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+
+    mixinMethod(): void;
+>mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.ts, 0, 17))
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.ts, 4, 15))
+>args : Symbol(args, Decl(mixinAbstractClasses.ts, 4, 48))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.ts, 4, 70))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.ts, 4, 15))
+>TBaseClass : Symbol(TBaseClass, Decl(mixinAbstractClasses.ts, 4, 15))
+>args : Symbol(args, Decl(mixinAbstractClasses.ts, 4, 122))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+
+    abstract class MixinClass extends baseClass implements Mixin {
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.ts, 4, 147))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.ts, 4, 70))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+
+        mixinMethod() {
+>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.ts, 5, 66))
+        }
+    }
+    return MixinClass;
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.ts, 4, 147))
+}
+
+class ConcreteBase {
+>ConcreteBase : Symbol(ConcreteBase, Decl(mixinAbstractClasses.ts, 10, 1))
+
+    baseMethod() {}
+>baseMethod : Symbol(ConcreteBase.baseMethod, Decl(mixinAbstractClasses.ts, 12, 20))
+}
+
+abstract class AbstractBase {
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.ts, 14, 1))
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.ts, 16, 29))
+}
+
+class DerivedFromConcrete extends Mixin(ConcreteBase) {
+>DerivedFromConcrete : Symbol(DerivedFromConcrete, Decl(mixinAbstractClasses.ts, 18, 1))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+>ConcreteBase : Symbol(ConcreteBase, Decl(mixinAbstractClasses.ts, 10, 1))
+}
+
+const wasConcrete = new DerivedFromConcrete();
+>wasConcrete : Symbol(wasConcrete, Decl(mixinAbstractClasses.ts, 23, 5))
+>DerivedFromConcrete : Symbol(DerivedFromConcrete, Decl(mixinAbstractClasses.ts, 18, 1))
+
+wasConcrete.baseMethod();
+>wasConcrete.baseMethod : Symbol(ConcreteBase.baseMethod, Decl(mixinAbstractClasses.ts, 12, 20))
+>wasConcrete : Symbol(wasConcrete, Decl(mixinAbstractClasses.ts, 23, 5))
+>baseMethod : Symbol(ConcreteBase.baseMethod, Decl(mixinAbstractClasses.ts, 12, 20))
+
+wasConcrete.mixinMethod();
+>wasConcrete.mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.ts, 0, 17))
+>wasConcrete : Symbol(wasConcrete, Decl(mixinAbstractClasses.ts, 23, 5))
+>mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.ts, 0, 17))
+
+class DerivedFromAbstract extends Mixin(AbstractBase) {
+>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.ts, 25, 26))
+>Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.ts, 2, 1), Decl(mixinAbstractClasses.ts, 0, 0))
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.ts, 14, 1))
+
+    abstractBaseMethod() {}
+>abstractBaseMethod : Symbol(DerivedFromAbstract.abstractBaseMethod, Decl(mixinAbstractClasses.ts, 27, 55))
+}
+
+const wasAbstract = new DerivedFromAbstract();
+>wasAbstract : Symbol(wasAbstract, Decl(mixinAbstractClasses.ts, 31, 5))
+>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.ts, 25, 26))
+
+wasAbstract.abstractBaseMethod();
+>wasAbstract.abstractBaseMethod : Symbol(DerivedFromAbstract.abstractBaseMethod, Decl(mixinAbstractClasses.ts, 27, 55))
+>wasAbstract : Symbol(wasAbstract, Decl(mixinAbstractClasses.ts, 31, 5))
+>abstractBaseMethod : Symbol(DerivedFromAbstract.abstractBaseMethod, Decl(mixinAbstractClasses.ts, 27, 55))
+
+wasAbstract.mixinMethod();
+>wasAbstract.mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.ts, 0, 17))
+>wasAbstract : Symbol(wasAbstract, Decl(mixinAbstractClasses.ts, 31, 5))
+>mixinMethod : Symbol(Mixin.mixinMethod, Decl(mixinAbstractClasses.ts, 0, 17))
+
diff --git a/tests/baselines/reference/mixinAbstractClasses.types b/tests/baselines/reference/mixinAbstractClasses.types
new file mode 100644
index 0000000000000..9dc6debbc5154
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClasses.types
@@ -0,0 +1,89 @@
+=== tests/cases/conformance/classes/mixinAbstractClasses.ts ===
+interface Mixin {
+    mixinMethod(): void;
+>mixinMethod : () => void
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+>Mixin : <TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass) => TBaseClass & (abstract new (...args: any) => Mixin)
+>args : any
+>baseClass : TBaseClass
+>args : any
+
+    abstract class MixinClass extends baseClass implements Mixin {
+>MixinClass : MixinClass
+>baseClass : TBaseClass
+
+        mixinMethod() {
+>mixinMethod : () => void
+        }
+    }
+    return MixinClass;
+>MixinClass : { new (...args: any): MixinClass; prototype: Mixin<any>.MixinClass; } & TBaseClass
+}
+
+class ConcreteBase {
+>ConcreteBase : ConcreteBase
+
+    baseMethod() {}
+>baseMethod : () => void
+}
+
+abstract class AbstractBase {
+>AbstractBase : AbstractBase
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : () => void
+}
+
+class DerivedFromConcrete extends Mixin(ConcreteBase) {
+>DerivedFromConcrete : DerivedFromConcrete
+>Mixin(ConcreteBase) : ConcreteBase & Mixin
+>Mixin : <TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass) => TBaseClass & (abstract new (...args: any) => Mixin)
+>ConcreteBase : typeof ConcreteBase
+}
+
+const wasConcrete = new DerivedFromConcrete();
+>wasConcrete : DerivedFromConcrete
+>new DerivedFromConcrete() : DerivedFromConcrete
+>DerivedFromConcrete : typeof DerivedFromConcrete
+
+wasConcrete.baseMethod();
+>wasConcrete.baseMethod() : void
+>wasConcrete.baseMethod : () => void
+>wasConcrete : DerivedFromConcrete
+>baseMethod : () => void
+
+wasConcrete.mixinMethod();
+>wasConcrete.mixinMethod() : void
+>wasConcrete.mixinMethod : () => void
+>wasConcrete : DerivedFromConcrete
+>mixinMethod : () => void
+
+class DerivedFromAbstract extends Mixin(AbstractBase) {
+>DerivedFromAbstract : DerivedFromAbstract
+>Mixin(AbstractBase) : AbstractBase & Mixin
+>Mixin : <TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass) => TBaseClass & (abstract new (...args: any) => Mixin)
+>AbstractBase : typeof AbstractBase
+
+    abstractBaseMethod() {}
+>abstractBaseMethod : () => void
+}
+
+const wasAbstract = new DerivedFromAbstract();
+>wasAbstract : DerivedFromAbstract
+>new DerivedFromAbstract() : DerivedFromAbstract
+>DerivedFromAbstract : typeof DerivedFromAbstract
+
+wasAbstract.abstractBaseMethod();
+>wasAbstract.abstractBaseMethod() : void
+>wasAbstract.abstractBaseMethod : () => void
+>wasAbstract : DerivedFromAbstract
+>abstractBaseMethod : () => void
+
+wasAbstract.mixinMethod();
+>wasAbstract.mixinMethod() : void
+>wasAbstract.mixinMethod : () => void
+>wasAbstract : DerivedFromAbstract
+>mixinMethod : () => void
+
diff --git a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt
index 6ae542f0f2ff6..1ab3c94458146 100644
--- a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt
+++ b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt
@@ -34,18 +34,19 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,49): erro
 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2554: Expected 2 arguments, but got 0.
 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2555: Expected at least 1 arguments, but got 0.
+tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(73,1): error TS2511: Cannot create an instance of an abstract class.
 
 
-==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (27 errors) ====
+==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (28 errors) ====
     var numOrDate: number | Date;
     var strOrBoolean: string | boolean;
     var strOrNum: string | number;
     
-    // If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+    // If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
     // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
     var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; };
     numOrDate = new unionOfDifferentReturnType(10);
-    strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+    strOrBoolean = new unionOfDifferentReturnType("hello"); // error
     ~~~~~~~~~~~~
 !!! error TS2322: Type 'number | Date' is not assignable to type 'string | boolean'.
 !!! error TS2322:   Type 'number' is not assignable to type 'string | boolean'.
@@ -182,4 +183,10 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro
     strOrNum = new unionWithRestParameter3(); // error no call signature
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 !!! error TS2555: Expected at least 1 arguments, but got 0.
-!!! related TS6210 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts:65:37: An argument for 'a' was not provided.
\ No newline at end of file
+!!! related TS6210 tests/cases/conformance/types/union/unionTypeConstructSignatures.ts:65:37: An argument for 'a' was not provided.
+    
+    var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
+    new unionWithAbstractSignature('hello');
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2511: Cannot create an instance of an abstract class.
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/unionTypeConstructSignatures.js b/tests/baselines/reference/unionTypeConstructSignatures.js
index 668ad3f335da9..2f5bb59d305e1 100644
--- a/tests/baselines/reference/unionTypeConstructSignatures.js
+++ b/tests/baselines/reference/unionTypeConstructSignatures.js
@@ -3,11 +3,11 @@ var numOrDate: number | Date;
 var strOrBoolean: string | boolean;
 var strOrNum: string | number;
 
-// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
 // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
 var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; };
 numOrDate = new unionOfDifferentReturnType(10);
-strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+strOrBoolean = new unionOfDifferentReturnType("hello"); // error
 new unionOfDifferentReturnType1(true); // error in type of parameter
 
 var unionOfDifferentReturnType1: { new (a: number): number; new (a: string): string; } | { new (a: number): Date; new (a: string): boolean; };
@@ -68,17 +68,21 @@ strOrNum = new unionWithRestParameter3('hello'); // error no call signature
 strOrNum = new unionWithRestParameter3('hello', 10); // ok
 strOrNum = new unionWithRestParameter3('hello', 10, 11); // ok
 strOrNum = new unionWithRestParameter3('hello', "hello"); // wrong type
-strOrNum = new unionWithRestParameter3(); // error no call signature
+strOrNum = new unionWithRestParameter3(); // error no call signature
+
+var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
+new unionWithAbstractSignature('hello');
+
 
 //// [unionTypeConstructSignatures.js]
 var numOrDate;
 var strOrBoolean;
 var strOrNum;
-// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
 // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
 var unionOfDifferentReturnType;
 numOrDate = new unionOfDifferentReturnType(10);
-strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+strOrBoolean = new unionOfDifferentReturnType("hello"); // error
 new unionOfDifferentReturnType1(true); // error in type of parameter
 var unionOfDifferentReturnType1;
 numOrDate = new unionOfDifferentReturnType1(10);
@@ -130,3 +134,5 @@ strOrNum = new unionWithRestParameter3('hello', 10); // ok
 strOrNum = new unionWithRestParameter3('hello', 10, 11); // ok
 strOrNum = new unionWithRestParameter3('hello', "hello"); // wrong type
 strOrNum = new unionWithRestParameter3(); // error no call signature
+var unionWithAbstractSignature;
+new unionWithAbstractSignature('hello');
diff --git a/tests/baselines/reference/unionTypeConstructSignatures.symbols b/tests/baselines/reference/unionTypeConstructSignatures.symbols
index ce4cc97bc1b51..797a6e73ebe92 100644
--- a/tests/baselines/reference/unionTypeConstructSignatures.symbols
+++ b/tests/baselines/reference/unionTypeConstructSignatures.symbols
@@ -9,7 +9,7 @@ var strOrBoolean: string | boolean;
 var strOrNum: string | number;
 >strOrNum : Symbol(strOrNum, Decl(unionTypeConstructSignatures.ts, 2, 3))
 
-// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
 // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
 var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; };
 >unionOfDifferentReturnType : Symbol(unionOfDifferentReturnType, Decl(unionTypeConstructSignatures.ts, 6, 3))
@@ -21,7 +21,7 @@ numOrDate = new unionOfDifferentReturnType(10);
 >numOrDate : Symbol(numOrDate, Decl(unionTypeConstructSignatures.ts, 0, 3))
 >unionOfDifferentReturnType : Symbol(unionOfDifferentReturnType, Decl(unionTypeConstructSignatures.ts, 6, 3))
 
-strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+strOrBoolean = new unionOfDifferentReturnType("hello"); // error
 >strOrBoolean : Symbol(strOrBoolean, Decl(unionTypeConstructSignatures.ts, 1, 3))
 >unionOfDifferentReturnType : Symbol(unionOfDifferentReturnType, Decl(unionTypeConstructSignatures.ts, 6, 3))
 
@@ -244,3 +244,11 @@ strOrNum = new unionWithRestParameter3(); // error no call signature
 >strOrNum : Symbol(strOrNum, Decl(unionTypeConstructSignatures.ts, 2, 3))
 >unionWithRestParameter3 : Symbol(unionWithRestParameter3, Decl(unionTypeConstructSignatures.ts, 64, 3))
 
+var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
+>unionWithAbstractSignature : Symbol(unionWithAbstractSignature, Decl(unionTypeConstructSignatures.ts, 71, 3))
+>a : Symbol(a, Decl(unionTypeConstructSignatures.ts, 71, 47))
+>a : Symbol(a, Decl(unionTypeConstructSignatures.ts, 71, 77))
+
+new unionWithAbstractSignature('hello');
+>unionWithAbstractSignature : Symbol(unionWithAbstractSignature, Decl(unionTypeConstructSignatures.ts, 71, 3))
+
diff --git a/tests/baselines/reference/unionTypeConstructSignatures.types b/tests/baselines/reference/unionTypeConstructSignatures.types
index 27e1797588783..70171c4248ed5 100644
--- a/tests/baselines/reference/unionTypeConstructSignatures.types
+++ b/tests/baselines/reference/unionTypeConstructSignatures.types
@@ -8,7 +8,7 @@ var strOrBoolean: string | boolean;
 var strOrNum: string | number;
 >strOrNum : string | number
 
-// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
 // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
 var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; };
 >unionOfDifferentReturnType : (new (a: number) => number) | (new (a: number) => Date)
@@ -22,7 +22,7 @@ numOrDate = new unionOfDifferentReturnType(10);
 >unionOfDifferentReturnType : (new (a: number) => number) | (new (a: number) => Date)
 >10 : 10
 
-strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+strOrBoolean = new unionOfDifferentReturnType("hello"); // error
 >strOrBoolean = new unionOfDifferentReturnType("hello") : number | Date
 >strOrBoolean : string | boolean
 >new unionOfDifferentReturnType("hello") : number | Date
@@ -365,3 +365,13 @@ strOrNum = new unionWithRestParameter3(); // error no call signature
 >new unionWithRestParameter3() : string | number
 >unionWithRestParameter3 : (new (a: string, ...b: number[]) => string) | (new (a: string) => number)
 
+var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
+>unionWithAbstractSignature : (abstract new (a: string) => string) | (new (a: string) => string)
+>a : string
+>a : string
+
+new unionWithAbstractSignature('hello');
+>new unionWithAbstractSignature('hello') : any
+>unionWithAbstractSignature : (abstract new (a: string) => string) | (new (a: string) => string)
+>'hello' : "hello"
+
diff --git a/tests/cases/conformance/classes/mixinAbstractClasses.2.ts b/tests/cases/conformance/classes/mixinAbstractClasses.2.ts
new file mode 100644
index 0000000000000..0a4867dfc9521
--- /dev/null
+++ b/tests/cases/conformance/classes/mixinAbstractClasses.2.ts
@@ -0,0 +1,27 @@
+// @target: esnext
+// @declaration: true
+
+interface Mixin {
+    mixinMethod(): void;
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+    abstract class MixinClass extends baseClass implements Mixin {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+const MixedBase = Mixin(AbstractBase);
+
+// error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+class DerivedFromAbstract extends MixedBase {
+}
+
+// error expected: Cannot create an instance of an abstract class.
+new MixedBase();
\ No newline at end of file
diff --git a/tests/cases/conformance/classes/mixinAbstractClasses.ts b/tests/cases/conformance/classes/mixinAbstractClasses.ts
new file mode 100644
index 0000000000000..5bfad6b769a3e
--- /dev/null
+++ b/tests/cases/conformance/classes/mixinAbstractClasses.ts
@@ -0,0 +1,37 @@
+// @target: esnext
+// @declaration: true
+
+interface Mixin {
+    mixinMethod(): void;
+}
+
+function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
+    abstract class MixinClass extends baseClass implements Mixin {
+        mixinMethod() {
+        }
+    }
+    return MixinClass;
+}
+
+class ConcreteBase {
+    baseMethod() {}
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+class DerivedFromConcrete extends Mixin(ConcreteBase) {
+}
+
+const wasConcrete = new DerivedFromConcrete();
+wasConcrete.baseMethod();
+wasConcrete.mixinMethod();
+
+class DerivedFromAbstract extends Mixin(AbstractBase) {
+    abstractBaseMethod() {}
+}
+
+const wasAbstract = new DerivedFromAbstract();
+wasAbstract.abstractBaseMethod();
+wasAbstract.mixinMethod();
\ No newline at end of file
diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts
index 3be629b86ba88..afcb58aff5d64 100644
--- a/tests/cases/conformance/types/conditional/inferTypes1.ts
+++ b/tests/cases/conformance/types/conditional/inferTypes1.ts
@@ -24,6 +24,11 @@ class C {
     y = 0;
 }
 
+abstract class Abstract {
+    x = 0;
+    y = 0;
+}
+
 type T10 = ReturnType<() => string>;  // string
 type T11 = ReturnType<(s: string) => void>;  // void
 type T12 = ReturnType<(<T>() => T)>;  // {}
@@ -40,6 +45,9 @@ type U11 = InstanceType<any>;  // any
 type U12 = InstanceType<never>;  // never
 type U13 = InstanceType<string>;  // Error
 type U14 = InstanceType<Function>;  // Error
+type U15 = InstanceType<typeof Abstract>;  // Abstract
+type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
+type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
 
 type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
 
diff --git a/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts b/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts
index 8f38e38aee062..3e0d509fe97f3 100644
--- a/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts
+++ b/tests/cases/conformance/types/union/unionTypeConstructSignatures.ts
@@ -2,11 +2,11 @@
 var strOrBoolean: string | boolean;
 var strOrNum: string | number;
 
-// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types, 
+// If each type in U has construct signatures and the sets of construct signatures are identical ignoring return types,
 // U has the same set of construct signatures, but with return types that are unions of the return types of the respective construct signatures from each type in U.
 var unionOfDifferentReturnType: { new (a: number): number; } | { new (a: number): Date; };
 numOrDate = new unionOfDifferentReturnType(10);
-strOrBoolean = new unionOfDifferentReturnType("hello"); // error 
+strOrBoolean = new unionOfDifferentReturnType("hello"); // error
 new unionOfDifferentReturnType1(true); // error in type of parameter
 
 var unionOfDifferentReturnType1: { new (a: number): number; new (a: string): string; } | { new (a: number): Date; new (a: string): boolean; };
@@ -67,4 +67,7 @@ strOrNum = new unionWithRestParameter3('hello'); // error no call signature
 strOrNum = new unionWithRestParameter3('hello', 10); // ok
 strOrNum = new unionWithRestParameter3('hello', 10, 11); // ok
 strOrNum = new unionWithRestParameter3('hello', "hello"); // wrong type
-strOrNum = new unionWithRestParameter3(); // error no call signature
\ No newline at end of file
+strOrNum = new unionWithRestParameter3(); // error no call signature
+
+var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
+new unionWithAbstractSignature('hello');

From a2c3dc78303326441266eb80ed3b42b59d9dcaab Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Fri, 10 Jul 2020 16:44:36 -0700
Subject: [PATCH 2/6] Add backwards-compatible overloads for creating/updating
 constructor types

---
 src/compiler/checker.ts                       |  6 ++--
 src/compiler/factory/nodeFactory.ts           | 35 +++++++++++++++++--
 src/compiler/types.ts                         |  4 +++
 .../reference/api/tsserverlibrary.d.ts        |  4 +++
 tests/baselines/reference/api/typescript.d.ts |  4 +++
 5 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 50b35745a0664..1a221a3f2a793 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -26570,7 +26570,7 @@ namespace ts {
                 if (!isConstructorAccessible(node, constructSignatures[0])) {
                     return resolveErrorCall(node);
                 }
-                // If the expression is a class of abstract type, or an abstract construct signature, 
+                // If the expression is a class of abstract type, or an abstract construct signature,
                 // 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.
@@ -30720,7 +30720,7 @@ namespace ts {
                 const implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent;
                 return implementationSharesContainerWithFirstOverload ? implementation! : overloads[0];
             }
-    
+
             function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void {
                 // Error if some overloads have a flag that is not shared by all overloads. To find the
                 // deviations, we XOR someOverloadFlags with allOverloadFlags
@@ -30744,7 +30744,7 @@ namespace ts {
                     });
                 }
             }
-    
+
             function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void {
                 if (someHaveQuestionToken !== allHaveQuestionToken) {
                     const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation));
diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts
index 0b2c60e863778..d7e7baf218c33 100644
--- a/src/compiler/factory/nodeFactory.ts
+++ b/src/compiler/factory/nodeFactory.ts
@@ -1647,7 +1647,13 @@ namespace ts {
         }
 
         // @api
-        function createConstructorTypeNode(
+        function createConstructorTypeNode(...args: Parameters<typeof createConstructorTypeNode1 | typeof createConstructorTypeNode2>) {
+            return args.length === 4 ? createConstructorTypeNode1(...args) :
+                args.length === 3 ? createConstructorTypeNode2(...args) :
+                Debug.fail("Incorrect number of arguments specified.");
+        }
+
+        function createConstructorTypeNode1(
             modifiers: readonly Modifier[] | undefined,
             typeParameters: readonly TypeParameterDeclaration[] | undefined,
             parameters: readonly ParameterDeclaration[],
@@ -1666,8 +1672,23 @@ namespace ts {
             return node;
         }
 
+        /** @deprecated */
+        function createConstructorTypeNode2(
+            typeParameters: readonly TypeParameterDeclaration[] | undefined,
+            parameters: readonly ParameterDeclaration[],
+            type: TypeNode | undefined
+        ): ConstructorTypeNode {
+            return createConstructorTypeNode1(/*modifiers*/ undefined, typeParameters, parameters, type);
+        }
+
         // @api
-        function updateConstructorTypeNode(
+        function updateConstructorTypeNode(...args: Parameters<typeof updateConstructorTypeNode1 | typeof updateConstructorTypeNode2>) {
+            return args.length === 5 ? updateConstructorTypeNode1(...args) :
+                args.length === 4 ? updateConstructorTypeNode2(...args) :
+                Debug.fail("Incorrect number of arguments specified.");
+        }
+
+        function updateConstructorTypeNode1(
             node: ConstructorTypeNode,
             modifiers: readonly Modifier[] | undefined,
             typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
@@ -1682,6 +1703,16 @@ namespace ts {
                 : node;
         }
 
+        /** @deprecated */
+        function updateConstructorTypeNode2(
+            node: ConstructorTypeNode,
+            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
+            parameters: NodeArray<ParameterDeclaration>,
+            type: TypeNode | undefined
+        ) {
+            return updateConstructorTypeNode1(node, node.modifiers, typeParameters, parameters, type);
+        }
+
         // @api
         function createTypeQueryNode(exprName: EntityName) {
             const node = createBaseNode<TypeQueryNode>(SyntaxKind.TypeQuery);
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 54cf3cd339797..d88a63b0c876d 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -6672,7 +6672,11 @@ namespace ts {
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
         createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
         updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index 6320f680ff8e8..e0d3e8bf8f904 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -3149,7 +3149,11 @@ declare namespace ts {
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
         createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
         updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index e007b7cbed0fa..d61fd4941b520 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -3149,7 +3149,11 @@ declare namespace ts {
         createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): FunctionTypeNode;
         updateFunctionTypeNode(node: FunctionTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): FunctionTypeNode;
         createConstructorTypeNode(modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        createConstructorTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): ConstructorTypeNode;
         updateConstructorTypeNode(node: ConstructorTypeNode, modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
+        /** @deprecated */
+        updateConstructorTypeNode(node: ConstructorTypeNode, typeParameters: NodeArray<TypeParameterDeclaration> | undefined, parameters: NodeArray<ParameterDeclaration>, type: TypeNode): ConstructorTypeNode;
         createTypeQueryNode(exprName: EntityName): TypeQueryNode;
         updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName): TypeQueryNode;
         createTypeLiteralNode(members: readonly TypeElement[] | undefined): TypeLiteralNode;

From 42528abebfb6a8b63651e0fab302cbc67d72233c Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Fri, 10 Jul 2020 17:15:57 -0700
Subject: [PATCH 3/6] Reverting use of 'abstract' in lib/es5.d.ts due to eslint
 issues

---
 src/lib/es5.d.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts
index d66023294c1f2..544cf09041d20 100644
--- a/src/lib/es5.d.ts
+++ b/src/lib/es5.d.ts
@@ -1496,7 +1496,7 @@ type Parameters<T extends (...args: any) => any> = T extends (...args: infer P)
 /**
  * Obtain the parameters of a constructor function type in a tuple
  */
-type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
+type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
 
 /**
  * Obtain the return type of a function type
@@ -1506,7 +1506,7 @@ type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => i
 /**
  * Obtain the return type of a constructor function type
  */
-type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
+type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any;
 
 /**
  * Marker for contextual 'this' type

From 65a49a78301c525dd0a0716e33ed7520a583a490 Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Mon, 13 Jul 2020 11:35:26 -0700
Subject: [PATCH 4/6] Update baseline due to reverting lib

---
 src/compiler/debug.ts                         |  2 +-
 .../reference/inferTypes1.errors.txt          | 20 ++++++++++++++-----
 tests/baselines/reference/inferTypes1.types   |  4 ++--
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts
index 7d60ebd6e2c95..fc07dcc89977a 100644
--- a/src/compiler/debug.ts
+++ b/src/compiler/debug.ts
@@ -430,7 +430,7 @@ namespace ts {
 
             Object.defineProperties(objectAllocator.getSignatureConstructor().prototype, {
                 __debugFlags: { get(this: Signature) { return formatSignatureFlags(this.flags); } },
-                __debugSignatureToString: { value(this: Signature) { return this.checker?.signatureToString(this) } }
+                __debugSignatureToString: { value(this: Signature) { return this.checker?.signatureToString(this); } }
             });
 
             const nodeConstructors = [
diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt
index 82f384705352b..d1ab94f7af991 100644
--- a/tests/baselines/reference/inferTypes1.errors.txt
+++ b/tests/baselines/reference/inferTypes1.errors.txt
@@ -1,9 +1,13 @@
 tests/cases/conformance/types/conditional/inferTypes1.ts(36,23): error TS2344: Type 'string' does not satisfy the constraint '(...args: any) => any'.
 tests/cases/conformance/types/conditional/inferTypes1.ts(37,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any) => any'.
   Type 'Function' provides no match for the signature '(...args: any): any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(43,25): error TS2344: Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.
-tests/cases/conformance/types/conditional/inferTypes1.ts(44,25): error TS2344: Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(43,25): error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any) => any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(44,25): error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any) => any'.
   Type 'Function' provides no match for the signature 'new (...args: any): any'.
+tests/cases/conformance/types/conditional/inferTypes1.ts(45,25): error TS2344: Type 'typeof Abstract' does not satisfy the constraint 'new (...args: any) => any'.
+  Cannot assign an abstract constructor type to a non-abstract constructor type.
+tests/cases/conformance/types/conditional/inferTypes1.ts(47,42): error TS2344: Type 'abstract new (x: string, ...args: T) => T[]' does not satisfy the constraint 'new (...args: any) => any'.
+  Cannot assign an abstract constructor type to a non-abstract constructor type.
 tests/cases/conformance/types/conditional/inferTypes1.ts(55,25): error TS2344: Type '(x: string, y: string) => number' does not satisfy the constraint '(x: any) => any'.
 tests/cases/conformance/types/conditional/inferTypes1.ts(56,25): error TS2344: Type 'Function' does not satisfy the constraint '(x: any) => any'.
   Type 'Function' provides no match for the signature '(x: any): any'.
@@ -21,7 +25,7 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322:
   Type 'T' is not assignable to type 'symbol'.
 
 
-==== tests/cases/conformance/types/conditional/inferTypes1.ts (16 errors) ====
+==== tests/cases/conformance/types/conditional/inferTypes1.ts (18 errors) ====
     type Unpacked<T> =
         T extends (infer U)[] ? U :
         T extends (...args: any[]) => infer U ? U :
@@ -71,14 +75,20 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322:
     type U12 = InstanceType<never>;  // never
     type U13 = InstanceType<string>;  // Error
                             ~~~~~~
-!!! error TS2344: Type 'string' does not satisfy the constraint 'abstract new (...args: any) => any'.
+!!! error TS2344: Type 'string' does not satisfy the constraint 'new (...args: any) => any'.
     type U14 = InstanceType<Function>;  // Error
                             ~~~~~~~~
-!!! error TS2344: Type 'Function' does not satisfy the constraint 'abstract new (...args: any) => any'.
+!!! error TS2344: Type 'Function' does not satisfy the constraint 'new (...args: any) => any'.
 !!! error TS2344:   Type 'Function' provides no match for the signature 'new (...args: any): any'.
     type U15 = InstanceType<typeof Abstract>;  // Abstract
+                            ~~~~~~~~~~~~~~~
+!!! error TS2344: Type 'typeof Abstract' does not satisfy the constraint 'new (...args: any) => any'.
+!!! error TS2344:   Cannot assign an abstract constructor type to a non-abstract constructor type.
     type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
     type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
+                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2344: Type 'abstract new (x: string, ...args: T) => T[]' does not satisfy the constraint 'new (...args: any) => any'.
+!!! error TS2344:   Cannot assign an abstract constructor type to a non-abstract constructor type.
     
     type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
     
diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types
index fec5a699c57d0..66e4c00ccbbdc 100644
--- a/tests/baselines/reference/inferTypes1.types
+++ b/tests/baselines/reference/inferTypes1.types
@@ -117,7 +117,7 @@ type U14 = InstanceType<Function>;  // Error
 >U14 : any
 
 type U15 = InstanceType<typeof Abstract>;  // Abstract
->U15 : Abstract
+>U15 : any
 >Abstract : typeof Abstract
 
 type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  // T[]
@@ -126,7 +126,7 @@ type U16<T extends any[]> = InstanceType<new (x: string, ...args: T) => T[]>;  /
 >args : T
 
 type U17<T extends any[]> = InstanceType<abstract new (x: string, ...args: T) => T[]>;  // T[]
->U17 : T[]
+>U17 : any
 >x : string
 >args : T
 

From 58753bbd9b983ab1337a50c68a84f37566e20d4e Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Tue, 8 Sep 2020 18:18:19 -0700
Subject: [PATCH 5/6] Add error for failing to mark an mixin class as abstract

---
 src/compiler/checker.ts                       | 12 ++++++++++--
 src/compiler/diagnosticMessages.json          |  4 ++++
 .../mixinAbstractClasses.2.errors.txt         | 12 ++++++++----
 .../reference/mixinAbstractClasses.2.js       |  4 +++-
 .../reference/mixinAbstractClasses.2.symbols  | 19 ++++++++++---------
 .../reference/mixinAbstractClasses.2.types    |  3 ++-
 .../classes/mixinAbstractClasses.2.ts         |  3 ++-
 7 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 908752d214680..1f3ef7782ce57 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -34616,8 +34616,16 @@ namespace ts {
                         checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
                             Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
                     }
-                    if (baseConstructorType.flags & TypeFlags.TypeVariable && !isMixinConstructorType(staticType)) {
-                        error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
+                    if (baseConstructorType.flags & TypeFlags.TypeVariable) {
+                        if (!isMixinConstructorType(staticType)) {
+                            error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
+                        }
+                        else {
+                            const constructSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
+                            if (constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) && !hasSyntacticModifier(node, ModifierFlags.Abstract)) {
+                                error(node.name || node, Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract);
+                            }
+                        }
                     }
 
                     if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) {
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index d348c49048022..afdef311b6810 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -3028,6 +3028,10 @@
         "category": "Error",
         "code": 2792
     },
+    "A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.": {
+        "category": "Error",
+        "code": 2793
+    },
 
     "Import declaration '{0}' is using private name '{1}'.": {
         "category": "Error",
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.errors.txt b/tests/baselines/reference/mixinAbstractClasses.2.errors.txt
index d009651f6ce3d..98570541f0870 100644
--- a/tests/baselines/reference/mixinAbstractClasses.2.errors.txt
+++ b/tests/baselines/reference/mixinAbstractClasses.2.errors.txt
@@ -1,14 +1,18 @@
-tests/cases/conformance/classes/mixinAbstractClasses.2.ts(20,7): error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
-tests/cases/conformance/classes/mixinAbstractClasses.2.ts(24,1): error TS2511: Cannot create an instance of an abstract class.
+tests/cases/conformance/classes/mixinAbstractClasses.2.ts(7,11): error TS2793: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+tests/cases/conformance/classes/mixinAbstractClasses.2.ts(21,7): error TS2515: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
+tests/cases/conformance/classes/mixinAbstractClasses.2.ts(25,1): error TS2511: Cannot create an instance of an abstract class.
 
 
-==== tests/cases/conformance/classes/mixinAbstractClasses.2.ts (2 errors) ====
+==== tests/cases/conformance/classes/mixinAbstractClasses.2.ts (3 errors) ====
     interface Mixin {
         mixinMethod(): void;
     }
     
     function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
-        abstract class MixinClass extends baseClass implements Mixin {
+        // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+        class MixinClass extends baseClass implements Mixin {
+              ~~~~~~~~~~
+!!! error TS2793: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
             mixinMethod() {
             }
         }
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.js b/tests/baselines/reference/mixinAbstractClasses.2.js
index 8f1a4a5d9d928..b91e82763853f 100644
--- a/tests/baselines/reference/mixinAbstractClasses.2.js
+++ b/tests/baselines/reference/mixinAbstractClasses.2.js
@@ -4,7 +4,8 @@ interface Mixin {
 }
 
 function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
-    abstract class MixinClass extends baseClass implements Mixin {
+    // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+    class MixinClass extends baseClass implements Mixin {
         mixinMethod() {
         }
     }
@@ -26,6 +27,7 @@ new MixedBase();
 
 //// [mixinAbstractClasses.2.js]
 function Mixin(baseClass) {
+    // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
     class MixinClass extends baseClass {
         mixinMethod() {
         }
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.symbols b/tests/baselines/reference/mixinAbstractClasses.2.symbols
index b9de3f4654a64..194e88addc3d2 100644
--- a/tests/baselines/reference/mixinAbstractClasses.2.symbols
+++ b/tests/baselines/reference/mixinAbstractClasses.2.symbols
@@ -16,13 +16,14 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
 >args : Symbol(args, Decl(mixinAbstractClasses.2.ts, 4, 122))
 >Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
 
-    abstract class MixinClass extends baseClass implements Mixin {
+    // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+    class MixinClass extends baseClass implements Mixin {
 >MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
 >baseClass : Symbol(baseClass, Decl(mixinAbstractClasses.2.ts, 4, 70))
 >Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
 
         mixinMethod() {
->mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.2.ts, 5, 66))
+>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClasses.2.ts, 6, 57))
         }
     }
     return MixinClass;
@@ -30,24 +31,24 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
 }
 
 abstract class AbstractBase {
->AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 11, 1))
 
     abstract abstractBaseMethod(): void;
->abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 12, 29))
+>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 13, 29))
 }
 
 const MixedBase = Mixin(AbstractBase);
->MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
 >Mixin : Symbol(Mixin, Decl(mixinAbstractClasses.2.ts, 2, 1), Decl(mixinAbstractClasses.2.ts, 0, 0))
->AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 10, 1))
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 11, 1))
 
 // error expected: Non-abstract class 'DerivedFromAbstract' does not implement inherited abstract member 'abstractBaseMethod' from class 'AbstractBase & Mixin'.
 class DerivedFromAbstract extends MixedBase {
->DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.2.ts, 16, 38))
->MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+>DerivedFromAbstract : Symbol(DerivedFromAbstract, Decl(mixinAbstractClasses.2.ts, 17, 38))
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
 }
 
 // error expected: Cannot create an instance of an abstract class.
 new MixedBase();
->MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 16, 5))
+>MixedBase : Symbol(MixedBase, Decl(mixinAbstractClasses.2.ts, 17, 5))
 
diff --git a/tests/baselines/reference/mixinAbstractClasses.2.types b/tests/baselines/reference/mixinAbstractClasses.2.types
index cde5f90e98a28..cb2bbe7e605fc 100644
--- a/tests/baselines/reference/mixinAbstractClasses.2.types
+++ b/tests/baselines/reference/mixinAbstractClasses.2.types
@@ -10,7 +10,8 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
 >baseClass : TBaseClass
 >args : any
 
-    abstract class MixinClass extends baseClass implements Mixin {
+    // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+    class MixinClass extends baseClass implements Mixin {
 >MixinClass : MixinClass
 >baseClass : TBaseClass
 
diff --git a/tests/cases/conformance/classes/mixinAbstractClasses.2.ts b/tests/cases/conformance/classes/mixinAbstractClasses.2.ts
index 0a4867dfc9521..1c4798e076d10 100644
--- a/tests/cases/conformance/classes/mixinAbstractClasses.2.ts
+++ b/tests/cases/conformance/classes/mixinAbstractClasses.2.ts
@@ -6,7 +6,8 @@ interface Mixin {
 }
 
 function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => Mixin) {
-    abstract class MixinClass extends baseClass implements Mixin {
+    // error expected: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
+    class MixinClass extends baseClass implements Mixin {
         mixinMethod() {
         }
     }

From cfec2cae1b1c5fe8190e521156fc10247c1c9822 Mon Sep 17 00:00:00 2001
From: Ron Buckton <ron.buckton@microsoft.com>
Date: Thu, 7 Jan 2021 14:30:07 -0800
Subject: [PATCH 6/6] Fix declaration/quick info for abstract construct
 signatures

---
 src/compiler/checker.ts                       | 45 ++++++++++++-
 src/compiler/types.ts                         |  1 +
 ...clarationEmitLocalClassDeclarationMixin.js | 10 ++-
 ...rationEmitLocalClassDeclarationMixin.types |  6 +-
 .../reference/mixinAbstractClasses.types      |  2 +-
 ...mixinAbstractClassesReturnTypeInference.js | 63 +++++++++++++++++++
 ...AbstractClassesReturnTypeInference.symbols | 48 ++++++++++++++
 ...inAbstractClassesReturnTypeInference.types | 44 +++++++++++++
 ...mixinAbstractClassesReturnTypeInference.ts | 24 +++++++
 9 files changed, 232 insertions(+), 11 deletions(-)
 create mode 100644 tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js
 create mode 100644 tests/baselines/reference/mixinAbstractClassesReturnTypeInference.symbols
 create mode 100644 tests/baselines/reference/mixinAbstractClassesReturnTypeInference.types
 create mode 100644 tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 4cf37279a6063..52e56344b00b4 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -3816,6 +3816,23 @@ namespace ts {
                 members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
         }
 
+        function getResolvedTypeWithoutAbstractConstructSignatures(type: ResolvedType) {
+            if (type.constructSignatures.length === 0) return type;
+            if (type.objectTypeWithoutAbstractConstructSignatures) return type.objectTypeWithoutAbstractConstructSignatures;
+            const constructSignatures = filter(type.constructSignatures, signature => !(signature.flags & SignatureFlags.Abstract));
+            if (type.constructSignatures === constructSignatures) return type;
+            const typeCopy = createAnonymousType(
+                type.symbol,
+                type.members,
+                type.callSignatures,
+                some(constructSignatures) ? constructSignatures : emptyArray,
+                type.stringIndexInfo,
+                type.numberIndexInfo);
+            type.objectTypeWithoutAbstractConstructSignatures = typeCopy;
+            typeCopy.objectTypeWithoutAbstractConstructSignatures = typeCopy;
+            return typeCopy;
+        }
+
         function forEachSymbolTableInScope<T>(enclosingDeclaration: Node | undefined, callback: (symbolTable: SymbolTable) => T): T {
             let result: T;
             for (let location = enclosingDeclaration; location; location = location.parent) {
@@ -4762,13 +4779,38 @@ namespace ts {
                         }
                     }
 
+                    const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract));
+                    if (some(abstractSignatures)) {
+                        const types = map(abstractSignatures, getOrCreateTypeFromSignature);
+                        // count the number of type elements excluding abstract constructors
+                        const typeElementCount =
+                            resolved.callSignatures.length +
+                            (resolved.constructSignatures.length - abstractSignatures.length) +
+                            (resolved.stringIndexInfo ? 1 : 0) +
+                            (resolved.numberIndexInfo ? 1 : 0) +
+                            // exclude `prototype` when writing a class expression as a type literal, as per
+                            // the logic in `createTypeNodesFromResolvedType`.
+                            (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral ?
+                                countWhere(resolved.properties, p => !(p.flags & SymbolFlags.Prototype)) :
+                                length(resolved.properties));
+                        // don't include an empty object literal if there were no other static-side
+                        // properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}`
+                        // and not `(abstract new () => {}) & {}`
+                        if (typeElementCount) {
+                            // create a copy of the object type without any abstract construct signatures.
+                            types.push(getResolvedTypeWithoutAbstractConstructSignatures(resolved));
+                        }
+                        return typeToTypeNodeHelper(getIntersectionType(types), context);
+                    }
+
                     const savedFlags = context.flags;
                     context.flags |= NodeBuilderFlags.InObjectTypeLiteral;
                     const members = createTypeNodesFromResolvedType(resolved);
                     context.flags = savedFlags;
                     const typeLiteralNode = factory.createTypeLiteralNode(members);
                     context.approximateLength += 2;
-                    return setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine);
+                    setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine);
+                    return typeLiteralNode;
                 }
 
                 function typeReferenceToTypeNode(type: TypeReference) {
@@ -4938,6 +4980,7 @@ namespace ts {
                         typeElements.push(<CallSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context));
                     }
                     for (const signature of resolvedType.constructSignatures) {
+                        if (signature.flags & SignatureFlags.Abstract) continue;
                         typeElements.push(<ConstructSignatureDeclaration>signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, context));
                     }
                     if (resolvedType.stringIndexInfo) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 5f7a2c0394478..70462b19ed186 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -5172,6 +5172,7 @@ namespace ts {
         /* @internal */ constructSignatures?: readonly Signature[]; // Construct signatures of type
         /* @internal */ stringIndexInfo?: IndexInfo;      // String indexing info
         /* @internal */ numberIndexInfo?: IndexInfo;      // Numeric indexing info
+        /* @internal */ objectTypeWithoutAbstractConstructSignatures?: ObjectType;
     }
 
     /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */
diff --git a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js
index 73399ba507a72..eff59f1c5389a 100644
--- a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js
+++ b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js
@@ -104,12 +104,10 @@ export declare const Mixed: {
         bar: number;
     };
 } & typeof Unmixed;
-declare const FilteredThing_base: {
-    new (...args: any[]): {
-        match(path: string): boolean;
-        thing: number;
-    };
-} & typeof Unmixed;
+declare const FilteredThing_base: (abstract new (...args: any[]) => {
+    match(path: string): boolean;
+    thing: number;
+}) & typeof Unmixed;
 export declare class FilteredThing extends FilteredThing_base {
     match(path: string): boolean;
 }
diff --git a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.types b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.types
index b63fd97e1ec2f..6a8bd24273f07 100644
--- a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.types
+++ b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.types
@@ -33,7 +33,7 @@ export const Mixed = mixin(Unmixed);
 >Unmixed : typeof Unmixed
 
 function Filter<C extends Constructor<{}>>(ctor: C) {
->Filter : <C extends Constructor<{}>>(ctor: C) => { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
+>Filter : <C extends Constructor<{}>>(ctor: C) => ((abstract new (...args: any[]) => FilterMixin) & { prototype: Filter<any>.FilterMixin; }) & C
 >ctor : C
 
     abstract class FilterMixin extends ctor {
@@ -50,13 +50,13 @@ function Filter<C extends Constructor<{}>>(ctor: C) {
 >12 : 12
     }
     return FilterMixin;
->FilterMixin : { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
+>FilterMixin : ((abstract new (...args: any[]) => FilterMixin) & { prototype: Filter<any>.FilterMixin; }) & C
 }
 
 export class FilteredThing extends Filter(Unmixed) {
 >FilteredThing : FilteredThing
 >Filter(Unmixed) : Filter<typeof Unmixed>.FilterMixin & Unmixed
->Filter : <C extends Constructor<{}>>(ctor: C) => { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
+>Filter : <C extends Constructor<{}>>(ctor: C) => ((abstract new (...args: any[]) => FilterMixin) & { prototype: Filter<any>.FilterMixin; }) & C
 >Unmixed : typeof Unmixed
 
     match(path: string) {
diff --git a/tests/baselines/reference/mixinAbstractClasses.types b/tests/baselines/reference/mixinAbstractClasses.types
index 9dc6debbc5154..aba29eb94c241 100644
--- a/tests/baselines/reference/mixinAbstractClasses.types
+++ b/tests/baselines/reference/mixinAbstractClasses.types
@@ -19,7 +19,7 @@ function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass:
         }
     }
     return MixinClass;
->MixinClass : { new (...args: any): MixinClass; prototype: Mixin<any>.MixinClass; } & TBaseClass
+>MixinClass : ((abstract new (...args: any) => MixinClass) & { prototype: Mixin<any>.MixinClass; }) & TBaseClass
 }
 
 class ConcreteBase {
diff --git a/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js
new file mode 100644
index 0000000000000..afdbfdf995f73
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.js
@@ -0,0 +1,63 @@
+//// [mixinAbstractClassesReturnTypeInference.ts]
+interface Mixin1 {
+    mixinMethod(): void;
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+function Mixin2<TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) {
+    // must be `abstract` because we cannot know *all* of the possible abstract members that need to be
+    // implemented for this to be concrete.
+    abstract class MixinClass extends baseClass implements Mixin1 {
+        mixinMethod(): void {}
+        static staticMixinMethod(): void {}
+    }
+    return MixinClass;
+}
+
+class DerivedFromAbstract2 extends Mixin2(AbstractBase) {
+    abstractBaseMethod() {}
+}
+
+
+//// [mixinAbstractClassesReturnTypeInference.js]
+class AbstractBase {
+}
+function Mixin2(baseClass) {
+    // must be `abstract` because we cannot know *all* of the possible abstract members that need to be
+    // implemented for this to be concrete.
+    class MixinClass extends baseClass {
+        mixinMethod() { }
+        static staticMixinMethod() { }
+    }
+    return MixinClass;
+}
+class DerivedFromAbstract2 extends Mixin2(AbstractBase) {
+    abstractBaseMethod() { }
+}
+
+
+//// [mixinAbstractClassesReturnTypeInference.d.ts]
+interface Mixin1 {
+    mixinMethod(): void;
+}
+declare abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+declare function Mixin2<TBase extends abstract new (...args: any[]) => any>(baseClass: TBase): ((abstract new (...args: any[]) => {
+    [x: string]: any;
+    mixinMethod(): void;
+}) & {
+    staticMixinMethod(): void;
+}) & TBase;
+declare const DerivedFromAbstract2_base: ((abstract new (...args: any[]) => {
+    [x: string]: any;
+    mixinMethod(): void;
+}) & {
+    staticMixinMethod(): void;
+}) & typeof AbstractBase;
+declare class DerivedFromAbstract2 extends DerivedFromAbstract2_base {
+    abstractBaseMethod(): void;
+}
diff --git a/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.symbols b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.symbols
new file mode 100644
index 0000000000000..bf435467ed7ac
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.symbols
@@ -0,0 +1,48 @@
+=== tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts ===
+interface Mixin1 {
+>Mixin1 : Symbol(Mixin1, Decl(mixinAbstractClassesReturnTypeInference.ts, 0, 0))
+
+    mixinMethod(): void;
+>mixinMethod : Symbol(Mixin1.mixinMethod, Decl(mixinAbstractClassesReturnTypeInference.ts, 0, 18))
+}
+
+abstract class AbstractBase {
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClassesReturnTypeInference.ts, 2, 1))
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClassesReturnTypeInference.ts, 4, 29))
+}
+
+function Mixin2<TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) {
+>Mixin2 : Symbol(Mixin2, Decl(mixinAbstractClassesReturnTypeInference.ts, 6, 1))
+>TBase : Symbol(TBase, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 16))
+>args : Symbol(args, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 44))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 68))
+>TBase : Symbol(TBase, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 16))
+
+    // must be `abstract` because we cannot know *all* of the possible abstract members that need to be
+    // implemented for this to be concrete.
+    abstract class MixinClass extends baseClass implements Mixin1 {
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 87))
+>baseClass : Symbol(baseClass, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 68))
+>Mixin1 : Symbol(Mixin1, Decl(mixinAbstractClassesReturnTypeInference.ts, 0, 0))
+
+        mixinMethod(): void {}
+>mixinMethod : Symbol(MixinClass.mixinMethod, Decl(mixinAbstractClassesReturnTypeInference.ts, 11, 67))
+
+        static staticMixinMethod(): void {}
+>staticMixinMethod : Symbol(MixinClass.staticMixinMethod, Decl(mixinAbstractClassesReturnTypeInference.ts, 12, 30))
+    }
+    return MixinClass;
+>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClassesReturnTypeInference.ts, 8, 87))
+}
+
+class DerivedFromAbstract2 extends Mixin2(AbstractBase) {
+>DerivedFromAbstract2 : Symbol(DerivedFromAbstract2, Decl(mixinAbstractClassesReturnTypeInference.ts, 16, 1))
+>Mixin2 : Symbol(Mixin2, Decl(mixinAbstractClassesReturnTypeInference.ts, 6, 1))
+>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClassesReturnTypeInference.ts, 2, 1))
+
+    abstractBaseMethod() {}
+>abstractBaseMethod : Symbol(DerivedFromAbstract2.abstractBaseMethod, Decl(mixinAbstractClassesReturnTypeInference.ts, 18, 57))
+}
+
diff --git a/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.types b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.types
new file mode 100644
index 0000000000000..460d4c6891952
--- /dev/null
+++ b/tests/baselines/reference/mixinAbstractClassesReturnTypeInference.types
@@ -0,0 +1,44 @@
+=== tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts ===
+interface Mixin1 {
+    mixinMethod(): void;
+>mixinMethod : () => void
+}
+
+abstract class AbstractBase {
+>AbstractBase : AbstractBase
+
+    abstract abstractBaseMethod(): void;
+>abstractBaseMethod : () => void
+}
+
+function Mixin2<TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) {
+>Mixin2 : <TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) => ((abstract new (...args: any[]) => MixinClass) & { prototype: Mixin2<any>.MixinClass; staticMixinMethod(): void; }) & TBase
+>args : any[]
+>baseClass : TBase
+
+    // must be `abstract` because we cannot know *all* of the possible abstract members that need to be
+    // implemented for this to be concrete.
+    abstract class MixinClass extends baseClass implements Mixin1 {
+>MixinClass : MixinClass
+>baseClass : TBase
+
+        mixinMethod(): void {}
+>mixinMethod : () => void
+
+        static staticMixinMethod(): void {}
+>staticMixinMethod : () => void
+    }
+    return MixinClass;
+>MixinClass : ((abstract new (...args: any[]) => MixinClass) & { prototype: Mixin2<any>.MixinClass; staticMixinMethod(): void; }) & TBase
+}
+
+class DerivedFromAbstract2 extends Mixin2(AbstractBase) {
+>DerivedFromAbstract2 : DerivedFromAbstract2
+>Mixin2(AbstractBase) : Mixin2<typeof AbstractBase>.MixinClass & AbstractBase
+>Mixin2 : <TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) => ((abstract new (...args: any[]) => MixinClass) & { prototype: Mixin2<any>.MixinClass; staticMixinMethod(): void; }) & TBase
+>AbstractBase : typeof AbstractBase
+
+    abstractBaseMethod() {}
+>abstractBaseMethod : () => void
+}
+
diff --git a/tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts b/tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts
new file mode 100644
index 0000000000000..3adf08a6b6e51
--- /dev/null
+++ b/tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts
@@ -0,0 +1,24 @@
+// @target: esnext
+// @declaration: true
+
+interface Mixin1 {
+    mixinMethod(): void;
+}
+
+abstract class AbstractBase {
+    abstract abstractBaseMethod(): void;
+}
+
+function Mixin2<TBase extends abstract new (...args: any[]) => any>(baseClass: TBase) {
+    // must be `abstract` because we cannot know *all* of the possible abstract members that need to be
+    // implemented for this to be concrete.
+    abstract class MixinClass extends baseClass implements Mixin1 {
+        mixinMethod(): void {}
+        static staticMixinMethod(): void {}
+    }
+    return MixinClass;
+}
+
+class DerivedFromAbstract2 extends Mixin2(AbstractBase) {
+    abstractBaseMethod() {}
+}