Reset partial memberlist on defered circularity to calculate the correct members (#20179)

* Reset partial memberlist on defered circularity to calculate the correct members

* Remove return type
This commit is contained in:
Wesley Wigham 2017-12-22 11:41:39 -08:00 committed by GitHub
parent 7ad0d7b9fd
commit cedcba9285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 183 additions and 8 deletions

View file

@ -5123,11 +5123,11 @@ namespace ts {
return type.resolvedBaseTypes;
}
function resolveBaseTypesOfClass(type: InterfaceType): void {
type.resolvedBaseTypes = emptyArray;
function resolveBaseTypesOfClass(type: InterfaceType) {
type.resolvedBaseTypes = resolvingEmptyArray;
const baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type));
if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) {
return;
return type.resolvedBaseTypes = emptyArray;
}
const baseTypeNode = getBaseTypeNodeOfClass(type);
const typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode);
@ -5150,24 +5150,31 @@ namespace ts {
const constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode);
if (!constructors.length) {
error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
return;
return type.resolvedBaseTypes = emptyArray;
}
baseType = getReturnTypeOfSignature(constructors[0]);
}
if (baseType === unknownType) {
return;
return type.resolvedBaseTypes = emptyArray;
}
if (!isValidBaseType(baseType)) {
error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType));
return;
return type.resolvedBaseTypes = emptyArray;
}
if (type === baseType || hasBaseType(baseType, type)) {
error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
return;
return type.resolvedBaseTypes = emptyArray;
}
type.resolvedBaseTypes = [baseType];
if (type.resolvedBaseTypes === resolvingEmptyArray) {
// Circular reference, likely through instantiation of default parameters
// (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset
// as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a
// partial instantiation of the members without the base types fully resolved
(type as Type as ResolvedType).members = undefined;
}
return type.resolvedBaseTypes = [baseType];
}
function areAllOuterTypeParametersApplied(type: Type): boolean {

View file

@ -3,6 +3,7 @@
/* @internal */
namespace ts {
export const emptyArray: never[] = [] as never[];
export const resolvingEmptyArray: never[] = [] as never[];
export const emptyMap: ReadonlyMap<never> = createMap<never>();
export const externalHelpersModuleNameText = "tslib";

View file

@ -0,0 +1,52 @@
//// [circularConstraintYieldsAppropriateError.ts]
// https://github.com/Microsoft/TypeScript/issues/16861
class BaseType<T> {
bar: T
}
class NextType<C extends { someProp: any }, T = C['someProp']> extends BaseType<T> {
baz: string;
}
class Foo extends NextType<Foo> {
someProp: {
test: true
}
}
const foo = new Foo();
foo.bar.test
//// [circularConstraintYieldsAppropriateError.js]
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
// https://github.com/Microsoft/TypeScript/issues/16861
var BaseType = /** @class */ (function () {
function BaseType() {
}
return BaseType;
}());
var NextType = /** @class */ (function (_super) {
__extends(NextType, _super);
function NextType() {
return _super !== null && _super.apply(this, arguments) || this;
}
return NextType;
}(BaseType));
var Foo = /** @class */ (function (_super) {
__extends(Foo, _super);
function Foo() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Foo;
}(NextType));
var foo = new Foo();
foo.bar.test;

View file

@ -0,0 +1,48 @@
=== tests/cases/compiler/circularConstraintYieldsAppropriateError.ts ===
// https://github.com/Microsoft/TypeScript/issues/16861
class BaseType<T> {
>BaseType : Symbol(BaseType, Decl(circularConstraintYieldsAppropriateError.ts, 0, 0))
>T : Symbol(T, Decl(circularConstraintYieldsAppropriateError.ts, 1, 15))
bar: T
>bar : Symbol(BaseType.bar, Decl(circularConstraintYieldsAppropriateError.ts, 1, 19))
>T : Symbol(T, Decl(circularConstraintYieldsAppropriateError.ts, 1, 15))
}
class NextType<C extends { someProp: any }, T = C['someProp']> extends BaseType<T> {
>NextType : Symbol(NextType, Decl(circularConstraintYieldsAppropriateError.ts, 3, 1))
>C : Symbol(C, Decl(circularConstraintYieldsAppropriateError.ts, 5, 15))
>someProp : Symbol(someProp, Decl(circularConstraintYieldsAppropriateError.ts, 5, 26))
>T : Symbol(T, Decl(circularConstraintYieldsAppropriateError.ts, 5, 43))
>C : Symbol(C, Decl(circularConstraintYieldsAppropriateError.ts, 5, 15))
>BaseType : Symbol(BaseType, Decl(circularConstraintYieldsAppropriateError.ts, 0, 0))
>T : Symbol(T, Decl(circularConstraintYieldsAppropriateError.ts, 5, 43))
baz: string;
>baz : Symbol(NextType.baz, Decl(circularConstraintYieldsAppropriateError.ts, 5, 84))
}
class Foo extends NextType<Foo> {
>Foo : Symbol(Foo, Decl(circularConstraintYieldsAppropriateError.ts, 7, 1))
>NextType : Symbol(NextType, Decl(circularConstraintYieldsAppropriateError.ts, 3, 1))
>Foo : Symbol(Foo, Decl(circularConstraintYieldsAppropriateError.ts, 7, 1))
someProp: {
>someProp : Symbol(Foo.someProp, Decl(circularConstraintYieldsAppropriateError.ts, 9, 33))
test: true
>test : Symbol(test, Decl(circularConstraintYieldsAppropriateError.ts, 10, 15))
}
}
const foo = new Foo();
>foo : Symbol(foo, Decl(circularConstraintYieldsAppropriateError.ts, 15, 5))
>Foo : Symbol(Foo, Decl(circularConstraintYieldsAppropriateError.ts, 7, 1))
foo.bar.test
>foo.bar.test : Symbol(test, Decl(circularConstraintYieldsAppropriateError.ts, 10, 15))
>foo.bar : Symbol(BaseType.bar, Decl(circularConstraintYieldsAppropriateError.ts, 1, 19))
>foo : Symbol(foo, Decl(circularConstraintYieldsAppropriateError.ts, 15, 5))
>bar : Symbol(BaseType.bar, Decl(circularConstraintYieldsAppropriateError.ts, 1, 19))
>test : Symbol(test, Decl(circularConstraintYieldsAppropriateError.ts, 10, 15))

View file

@ -0,0 +1,50 @@
=== tests/cases/compiler/circularConstraintYieldsAppropriateError.ts ===
// https://github.com/Microsoft/TypeScript/issues/16861
class BaseType<T> {
>BaseType : BaseType<T>
>T : T
bar: T
>bar : T
>T : T
}
class NextType<C extends { someProp: any }, T = C['someProp']> extends BaseType<T> {
>NextType : NextType<C, T>
>C : C
>someProp : any
>T : T
>C : C
>BaseType : BaseType<T>
>T : T
baz: string;
>baz : string
}
class Foo extends NextType<Foo> {
>Foo : Foo
>NextType : NextType<Foo, { test: true; }>
>Foo : Foo
someProp: {
>someProp : { test: true; }
test: true
>test : true
>true : true
}
}
const foo = new Foo();
>foo : Foo
>new Foo() : Foo
>Foo : typeof Foo
foo.bar.test
>foo.bar.test : true
>foo.bar : { test: true; }
>foo : Foo
>bar : { test: true; }
>test : true

View file

@ -0,0 +1,17 @@
// https://github.com/Microsoft/TypeScript/issues/16861
class BaseType<T> {
bar: T
}
class NextType<C extends { someProp: any }, T = C['someProp']> extends BaseType<T> {
baz: string;
}
class Foo extends NextType<Foo> {
someProp: {
test: true
}
}
const foo = new Foo();
foo.bar.test