@@ -4571,33 +4571,43 @@ namespace ts {
4571
4571
getUnionType([info1.type, info2.type]), info1.isReadonly || info2.isReadonly);
4572
4572
}
4573
4573
4574
+ function includeMixinType(type: Type, types: Type[], index: number): Type {
4575
+ const mixedTypes: Type[] = [];
4576
+ for (let i = 0; i < types.length; i++) {
4577
+ if (i === index) {
4578
+ mixedTypes.push(type);
4579
+ }
4580
+ else if (isMixinConstructorType(types[i])) {
4581
+ mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], SignatureKind.Construct)[0]));
4582
+ }
4583
+ }
4584
+ return getIntersectionType(mixedTypes);
4585
+ }
4586
+
4574
4587
function resolveIntersectionTypeMembers(type: IntersectionType) {
4575
4588
// The members and properties collections are empty for intersection types. To get all properties of an
4576
4589
// intersection type use getPropertiesOfType (only the language service uses this).
4577
4590
let callSignatures: Signature[] = emptyArray;
4578
4591
let constructSignatures: Signature[] = emptyArray;
4579
4592
let stringIndexInfo: IndexInfo;
4580
4593
let numberIndexInfo: IndexInfo;
4581
- let mixinTypes: Type[] ;
4582
- const count = type. types.length ;
4583
- for (let i = 0; i < count ; i++) {
4594
+ const types = type.types ;
4595
+ const mixinCount = countWhere( types, isMixinConstructorType) ;
4596
+ for (let i = 0; i < types.length ; i++) {
4584
4597
const t = type.types[i];
4585
- // When a type T is preceded by a mixin constructor type, the return type of each construct signature
4586
- // in T is intersected with the return type of the mixin constructor, and the mixin construct signature
4587
- // is removed. For example, the intersection '{ new(...args: any[]) => A } & { new(s: string) => B }'
4588
- // has a single construct signature 'new(s: string) => A & B'.
4589
- let signatures = getSignaturesOfType(t, SignatureKind.Construct);
4590
- if (i < count - 1 && isMixinConstructorType(t)) {
4591
- (mixinTypes || (mixinTypes = [])).push(getReturnTypeOfSignature(signatures[0]));
4592
- }
4593
- else {
4594
- if (mixinTypes) {
4598
+ // When an intersection type contains mixin constructor types, the construct signatures from
4599
+ // those types are discarded and their return types are mixed into the return types of all
4600
+ // other construct signatures in the intersection type. For example, the intersection type
4601
+ // '{ new(...args: any[]) => A } & { new(s: string) => B }' has a single construct signature
4602
+ // 'new(s: string) => A & B'.
4603
+ if (mixinCount === 0 || mixinCount === types.length && i === 0 || !isMixinConstructorType(t)) {
4604
+ let signatures = getSignaturesOfType(t, SignatureKind.Construct);
4605
+ if (signatures.length && mixinCount > 0) {
4595
4606
signatures = map(signatures, s => {
4596
4607
const clone = cloneSignature(s);
4597
- clone.resolvedReturnType = getIntersectionType([...mixinTypes, getReturnTypeOfSignature(s)] );
4608
+ clone.resolvedReturnType = includeMixinType( getReturnTypeOfSignature(s), types, i );
4598
4609
return clone;
4599
4610
});
4600
- mixinTypes = undefined;
4601
4611
}
4602
4612
constructSignatures = concatenate(constructSignatures, signatures);
4603
4613
}
0 commit comments