diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 13dbc1c7886..e49e4492265 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3876,8 +3876,9 @@ namespace ts { function visitAndTransformType(type: Type, transform: (type: Type) => T) { const typeId = "" + type.id; const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; - const id = getObjectFlags(type) & ObjectFlags.Reference ? "N" + getNodeId((type).node) : - (isConstructorObject ? "+" : "") + getSymbolId(type.symbol); + const id = getObjectFlags(type) & ObjectFlags.Reference && (type).node ? "N" + getNodeId((type).node!) : + type.symbol ? (isConstructorObject ? "+" : "") + getSymbolId(type.symbol) : + undefined; // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead // of types allows us to catch circular references to instantiations of the same anonymous type if (!context.visitedTypes) { @@ -29347,12 +29348,9 @@ namespace ts { if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) { // When the static base type is a "class-like" constructor function (but not actually a class), we verify - // that all instantiated base constructor signatures return the same type. We can simply compare the type - // references (as opposed to checking the structure of the types) because elsewhere we have already checked - // that the base type is a class or interface type (and not, for example, an anonymous object type). - // (Javascript constructor functions have this property trivially true since their return type is ignored.) + // that all instantiated base constructor signatures return the same type. const constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); - if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && getReturnTypeOfSignature(sig) !== baseType)) { + if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType))) { error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ce4c6a90819..21f09ffcd5c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4203,14 +4203,18 @@ namespace ts { export interface TypeReference extends ObjectType { target: GenericType; // Type reference target node?: ArrayTypeNode | TupleTypeNode; + /* @internal */ mapper?: TypeMapper; + /* @internal */ resolvedTypeArguments?: ReadonlyArray; // Resolved ype reference type arguments /* @internal */ literalType?: TypeReference; // Clone of type with ObjectFlags.ArrayLiteral set } export interface DeferredTypeReference extends TypeReference { + /* @internal */ node: ArrayTypeNode | TupleTypeNode; + /* @internal */ mapper?: TypeMapper; }