Copy consistient valueDeclarations on union/intersection symbols (#23190)

This commit is contained in:
Wesley Wigham 2018-04-27 13:12:35 -07:00 committed by GitHub
parent bcb5599bf2
commit d5ef1174bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 2 deletions

View file

@ -6677,7 +6677,15 @@ namespace ts {
let nameType: Type;
const propTypes: Type[] = [];
let first = true;
let commonValueDeclaration: Declaration;
let hasNonUniformValueDeclaration = false;
for (const prop of props) {
if (!commonValueDeclaration) {
commonValueDeclaration = prop.valueDeclaration;
}
else if (prop.valueDeclaration !== commonValueDeclaration) {
hasNonUniformValueDeclaration = true;
}
declarations = addRange(declarations, prop.declarations);
const type = getTypeOfSymbol(prop);
if (first) {
@ -6694,6 +6702,9 @@ namespace ts {
}
const result = createSymbol(SymbolFlags.Property | commonFlags, name, syntheticFlag | checkFlags);
result.containingType = containingType;
if (!hasNonUniformValueDeclaration && commonValueDeclaration) {
result.valueDeclaration = commonValueDeclaration;
}
result.declarations = declarations;
result.nameType = nameType;
result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
@ -10774,13 +10785,14 @@ namespace ts {
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate) {
const hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration;
if (getCheckFlags(sourceProp) & CheckFlags.ContainsPrivate && hasDifferingDeclarations) {
if (reportErrors) {
reportError(Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source));
}
return Ternary.False;
}
if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
if (hasDifferingDeclarations) {
if (reportErrors) {
if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));

View file

@ -0,0 +1,42 @@
//// [doubleMixinConditionalTypeBaseClassWorks.ts]
type Constructor = new (...args: any[]) => {};
const Mixin1 = <C extends Constructor>(Base: C) => class extends Base { private _fooPrivate: {}; }
type FooConstructor = typeof Mixin1 extends (a: Constructor) => infer Cls ? Cls : never;
const Mixin2 = <C extends FooConstructor>(Base: C) => class extends Base {};
class C extends Mixin2(Mixin1(Object)) {}
//// [doubleMixinConditionalTypeBaseClassWorks.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 __());
};
})();
var Mixin1 = function (Base) { return /** @class */ (function (_super) {
__extends(class_1, _super);
function class_1() {
return _super !== null && _super.apply(this, arguments) || this;
}
return class_1;
}(Base)); };
var Mixin2 = function (Base) { return /** @class */ (function (_super) {
__extends(class_2, _super);
function class_2() {
return _super !== null && _super.apply(this, arguments) || this;
}
return class_2;
}(Base)); };
var C = /** @class */ (function (_super) {
__extends(C, _super);
function C() {
return _super !== null && _super.apply(this, arguments) || this;
}
return C;
}(Mixin2(Mixin1(Object))));

View file

@ -0,0 +1,36 @@
=== tests/cases/compiler/doubleMixinConditionalTypeBaseClassWorks.ts ===
type Constructor = new (...args: any[]) => {};
>Constructor : Symbol(Constructor, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 0, 0))
>args : Symbol(args, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 0, 24))
const Mixin1 = <C extends Constructor>(Base: C) => class extends Base { private _fooPrivate: {}; }
>Mixin1 : Symbol(Mixin1, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 5))
>C : Symbol(C, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 16))
>Constructor : Symbol(Constructor, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 0, 0))
>Base : Symbol(Base, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 39))
>C : Symbol(C, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 16))
>Base : Symbol(Base, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 39))
>_fooPrivate : Symbol((Anonymous class)._fooPrivate, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 71))
type FooConstructor = typeof Mixin1 extends (a: Constructor) => infer Cls ? Cls : never;
>FooConstructor : Symbol(FooConstructor, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 98))
>Mixin1 : Symbol(Mixin1, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 5))
>a : Symbol(a, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 4, 45))
>Constructor : Symbol(Constructor, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 0, 0))
>Cls : Symbol(Cls, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 4, 69))
>Cls : Symbol(Cls, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 4, 69))
const Mixin2 = <C extends FooConstructor>(Base: C) => class extends Base {};
>Mixin2 : Symbol(Mixin2, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 5))
>C : Symbol(C, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 16))
>FooConstructor : Symbol(FooConstructor, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 98))
>Base : Symbol(Base, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 42))
>C : Symbol(C, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 16))
>Base : Symbol(Base, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 42))
class C extends Mixin2(Mixin1(Object)) {}
>C : Symbol(C, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 76))
>Mixin2 : Symbol(Mixin2, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 5, 5))
>Mixin1 : Symbol(Mixin1, Decl(doubleMixinConditionalTypeBaseClassWorks.ts, 2, 5))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

View file

@ -0,0 +1,42 @@
=== tests/cases/compiler/doubleMixinConditionalTypeBaseClassWorks.ts ===
type Constructor = new (...args: any[]) => {};
>Constructor : Constructor
>args : any[]
const Mixin1 = <C extends Constructor>(Base: C) => class extends Base { private _fooPrivate: {}; }
>Mixin1 : <C extends Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
><C extends Constructor>(Base: C) => class extends Base { private _fooPrivate: {}; } : <C extends Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>C : C
>Constructor : Constructor
>Base : C
>C : C
>class extends Base { private _fooPrivate: {}; } : { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>Base : {}
>_fooPrivate : {}
type FooConstructor = typeof Mixin1 extends (a: Constructor) => infer Cls ? Cls : never;
>FooConstructor : { new (...args: any[]): <Constructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & Constructor
>Mixin1 : <C extends Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>a : Constructor
>Constructor : Constructor
>Cls : Cls
>Cls : Cls
const Mixin2 = <C extends FooConstructor>(Base: C) => class extends Base {};
>Mixin2 : <C extends { new (...args: any[]): <Constructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
><C extends FooConstructor>(Base: C) => class extends Base {} : <C extends { new (...args: any[]): <Constructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>C : C
>FooConstructor : { new (...args: any[]): <Constructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & Constructor
>Base : C
>C : C
>class extends Base {} : { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>Base : <Constructor>.(Anonymous class)
class C extends Mixin2(Mixin1(Object)) {}
>C : C
>Mixin2(Mixin1(Object)) : <{ new (...args: any[]): <ObjectConstructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & ObjectConstructor>.(Anonymous class) & <ObjectConstructor>.(Anonymous class) & Object
>Mixin2 : <C extends { new (...args: any[]): <Constructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>Mixin1(Object) : { new (...args: any[]): <ObjectConstructor>.(Anonymous class); prototype: <any>.(Anonymous class); } & ObjectConstructor
>Mixin1 : <C extends Constructor>(Base: C) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & C
>Object : ObjectConstructor

View file

@ -0,0 +1,8 @@
type Constructor = new (...args: any[]) => {};
const Mixin1 = <C extends Constructor>(Base: C) => class extends Base { private _fooPrivate: {}; }
type FooConstructor = typeof Mixin1 extends (a: Constructor) => infer Cls ? Cls : never;
const Mixin2 = <C extends FooConstructor>(Base: C) => class extends Base {};
class C extends Mixin2(Mixin1(Object)) {}