mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
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:
+95
-22
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -2131,6 +2131,7 @@ namespace ts {
|
||||
|
||||
function emitConstructorType(node: ConstructorTypeNode) {
|
||||
pushNameGenerationScope(node);
|
||||
emitModifiers(node, node.modifiers);
|
||||
writeKeyword("new");
|
||||
writeSpace();
|
||||
emitTypeParameters(node, node.typeParameters);
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user