Add support for abstract constructor types (#36392)

* Add support for abstract constructor types

* Add backwards-compatible overloads for creating/updating constructor types

* Reverting use of 'abstract' in lib/es5.d.ts due to eslint issues

* Update baseline due to reverting lib

* Add error for failing to mark an mixin class as abstract

* Fix declaration/quick info for abstract construct signatures
This commit is contained in:
Ron Buckton
2021-01-07 17:11:14 -08:00
committed by GitHub
parent 3273dbc188
commit 0d284e6c26
40 changed files with 1522 additions and 515 deletions
+95 -22
View File
@@ -3827,6 +3827,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) {
@@ -4773,13 +4790,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) {
@@ -4949,6 +4991,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) {
@@ -5221,23 +5264,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) {
@@ -5969,6 +6017,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,
@@ -9169,7 +9218,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;
}
@@ -10189,8 +10241,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);
@@ -10204,6 +10258,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);
}
}
@@ -11782,6 +11837,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);
@@ -18479,7 +18538,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,
@@ -28082,10 +28143,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);
@@ -32398,7 +32463,6 @@ namespace ts {
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) {
@@ -35699,8 +35763,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)) {
@@ -36980,8 +37052,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:
@@ -39251,7 +39323,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 &&
@@ -39365,6 +39438,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:
@@ -39374,7 +39448,6 @@ namespace ts {
return nodeHasAnyModifiersExcept(node, SyntaxKind.ConstKeyword);
default:
Debug.fail();
return false;
}
}
}
+9
View File
@@ -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);
}
@@ -573,6 +577,11 @@ namespace ts {
},
});
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(),
+4
View File
@@ -3231,6 +3231,10 @@
"category": "Error",
"code": 2796
},
"A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.": {
"category": "Error",
"code": 2797
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
+1
View File
@@ -2131,6 +2131,7 @@ namespace ts {
function emitConstructorType(node: ConstructorTypeNode) {
pushNameGenerationScope(node);
emitModifiers(node, node.modifiers);
writeKeyword("new");
writeSpace();
emitTypeParameters(node, node.typeParameters);
+42 -8
View File
@@ -1700,7 +1700,14 @@ 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[],
type: TypeNode | undefined
@@ -1708,7 +1715,7 @@ namespace ts {
const node = createBaseSignatureDeclaration<ConstructorTypeNode>(
SyntaxKind.ConstructorType,
/*decorators*/ undefined,
/*modifiers*/ undefined,
modifiers,
/*name*/ undefined,
typeParameters,
parameters,
@@ -1718,18 +1725,45 @@ 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,
parameters: NodeArray<ParameterDeclaration>,
type: TypeNode | undefined
) {
return node.modifiers !== modifiers
|| node.typeParameters !== typeParameters
|| node.parameters !== parameters
|| node.type !== type
? updateBaseSignatureDeclaration(createConstructorTypeNode(modifiers, typeParameters, parameters, type), node)
: node;
}
/** @deprecated */
function updateConstructorTypeNode2(
node: ConstructorTypeNode,
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
parameters: NodeArray<ParameterDeclaration>,
type: TypeNode | undefined
) {
return node.typeParameters !== typeParameters
|| node.parameters !== parameters
|| node.type !== type
? updateBaseSignatureDeclaration(createConstructorTypeNode(typeParameters, parameters, type), node)
: node;
return updateConstructorTypeNode1(node, node.modifiers, typeParameters, parameters, type);
}
// @api
+21 -2
View File
@@ -3368,16 +3368,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);
}
@@ -3678,6 +3691,11 @@ namespace ts {
return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode);
}
function nextTokenIsNewKeyword(): boolean {
nextToken();
return token() === SyntaxKind.NewKeyword;
}
function isStartOfFunctionTypeOrConstructorType(): boolean {
if (token() === SyntaxKind.LessThanToken) {
return true;
@@ -3685,7 +3703,8 @@ namespace ts {
if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) {
return true;
}
return token() === SyntaxKind.NewKeyword;
return token() === SyntaxKind.NewKeyword ||
token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword);
}
function skipParameterStart(): boolean {
+1 -1
View File
@@ -1017,7 +1017,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);
+15 -5
View File
@@ -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). */
@@ -5505,16 +5506,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
// We do not propagate `IsInnerCallChain` to instantiated signatures, as that would result in us
// 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` 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 | IsUntypedSignatureInJSFile,
PropagatingFlags = HasRestParameter | HasLiteralTypes | Abstract | IsUntypedSignatureInJSFile,
CallChainFlags = IsInnerCallChain | IsOuterCallChain,
}
@@ -6879,7 +6885,11 @@ 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(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;
+1 -6
View File
@@ -4751,7 +4751,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) {
@@ -5452,11 +5452,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);
+1
View File
@@ -485,6 +485,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));
+15 -2
View File
@@ -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);
+8
View File
@@ -220,6 +220,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());
}
@@ -245,6 +249,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());
}
+6 -2
View File
@@ -3234,7 +3234,11 @@ 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(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;
@@ -10522,9 +10526,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. */
+6 -2
View File
@@ -3234,7 +3234,11 @@ 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(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;
@@ -6857,9 +6861,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. */
@@ -1,6 +1,6 @@
tests/cases/compiler/assignmentCompatability45.ts(7,7): error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
Types of construct signatures are incompatible.
Type 'new (x: number) => B' is not assignable to type 'new () => A'.
Type 'new (x: number) => B' is not assignable to type 'abstract new () => A'.
==== tests/cases/compiler/assignmentCompatability45.ts (1 errors) ====
@@ -14,5 +14,5 @@ tests/cases/compiler/assignmentCompatability45.ts(7,7): error TS2322: Type 'type
~
!!! error TS2322: Type 'typeof B' is not assignable to type 'typeof A'.
!!! error TS2322: Types of construct signatures are incompatible.
!!! error TS2322: Type 'new (x: number) => B' is not assignable to type 'new () => A'.
!!! error TS2322: Type 'new (x: number) => B' is not assignable to type 'abstract new () => A'.
@@ -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;
}
@@ -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) {
@@ -1,27 +1,31 @@
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 '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(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(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'.
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'.
==== 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 :
@@ -45,6 +49,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)>; // {}
@@ -71,6 +80,15 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(145,40): error TS2322:
~~~~~~~~
!!! 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;
+15
View File
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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 : any
>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 : any
>x : string
>args : T
type ArgumentType<T extends (x: any) => any> = T extends (a: infer A) => any ? A : any;
>ArgumentType : ArgumentType<T>
>x : any
@@ -0,0 +1,37 @@
tests/cases/conformance/classes/mixinAbstractClasses.2.ts(7,11): error TS2797: 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 (3 errors) ====
interface Mixin {
mixinMethod(): void;
}
function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => 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 TS2797: A mixin class that extends from a type variable containing an abstract construct signature must also be declared 'abstract'.
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.
@@ -0,0 +1,57 @@
//// [mixinAbstractClasses.2.ts]
interface Mixin {
mixinMethod(): void;
}
function Mixin<TBaseClass extends abstract new (...args: any) => any>(baseClass: TBaseClass): TBaseClass & (abstract new (...args: any) => 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() {
}
}
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) {
// 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() {
}
}
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 {
}
@@ -0,0 +1,54 @@
=== 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))
// 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, 6, 57))
}
}
return MixinClass;
>MixinClass : Symbol(MixinClass, Decl(mixinAbstractClasses.2.ts, 4, 147))
}
abstract class AbstractBase {
>AbstractBase : Symbol(AbstractBase, Decl(mixinAbstractClasses.2.ts, 11, 1))
abstract abstractBaseMethod(): void;
>abstractBaseMethod : Symbol(AbstractBase.abstractBaseMethod, Decl(mixinAbstractClasses.2.ts, 13, 29))
}
const MixedBase = Mixin(AbstractBase);
>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, 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, 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, 17, 5))
@@ -0,0 +1,49 @@
=== 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
// 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
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)
@@ -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;
@@ -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))
@@ -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 : ((abstract 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
@@ -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;
}
@@ -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))
}
@@ -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
}
@@ -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.
!!! 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.
@@ -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');
@@ -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))
@@ -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"
@@ -0,0 +1,28 @@
// @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) {
// 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() {
}
}
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();
@@ -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();
@@ -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() {}
}
@@ -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;
@@ -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
strOrNum = new unionWithRestParameter3(); // error no call signature
var unionWithAbstractSignature: (abstract new (a: string) => string) | (new (a: string) => string);
new unionWithAbstractSignature('hello');