@@ -3050,42 +3050,55 @@ namespace ts {
3050
3050
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
3051
3051
}
3052
3052
3053
- function signatureListsIdentical(s: Signature[], t: Signature[]): boolean {
3054
- if (s.length !== t.length) {
3055
- return false;
3053
+ function findMatchingSignature(signature: Signature, signatureList: Signature[]): Signature {
3054
+ for (let s of signatureList) {
3055
+ // Only signatures with no type parameters may differ in return types
3056
+ if (compareSignatures(signature, s, /*compareReturnTypes*/ !!signature.typeParameters, compareTypes)) {
3057
+ return s;
3058
+ }
3056
3059
}
3057
- for (let i = 0; i < s.length; i++) {
3058
- if (!compareSignatures(s[i], t[i], /*compareReturnTypes*/ false, compareTypes)) {
3059
- return false;
3060
+ }
3061
+
3062
+ function findMatchingSignatures(signature: Signature, signatureLists: Signature[][]): Signature[] {
3063
+ let result: Signature[] = undefined;
3064
+ for (let i = 1; i < signatureLists.length; i++) {
3065
+ let match = findMatchingSignature(signature, signatureLists[i]);
3066
+ if (!match) {
3067
+ return undefined;
3068
+ }
3069
+ if (!result) {
3070
+ result = [signature];
3071
+ }
3072
+ if (match !== signature) {
3073
+ result.push(match);
3060
3074
}
3061
3075
}
3062
- return true ;
3076
+ return result ;
3063
3077
}
3064
3078
3065
- // If the lists of call or construct signatures in the given types are all identical except for return types,
3066
- // and if none of the signatures are generic, return a list of signatures that has substitutes a union of the
3067
- // return types of the corresponding signatures in each resulting signature .
3079
+ // The signatures of a union type are those signatures that are present and identical in each of the
3080
+ // constituent types, except that non- generic signatures may differ in return types. When signatures
3081
+ // differ in return types, the resulting return type is the union of the constituent return types .
3068
3082
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
3069
3083
let signatureLists = map(types, t => getSignaturesOfType(t, kind));
3070
- let signatures = signatureLists[0];
3071
- for (let signature of signatures) {
3072
- if (signature.typeParameters) {
3073
- return emptyArray;
3074
- }
3075
- }
3076
- for (let i = 1; i < signatureLists.length; i++) {
3077
- if (!signatureListsIdentical(signatures, signatureLists[i])) {
3078
- return emptyArray;
3084
+ let result: Signature[] = undefined;
3085
+ for (let source of signatureLists[0]) {
3086
+ let unionSignatures = findMatchingSignatures(source, signatureLists);
3087
+ if (unionSignatures) {
3088
+ let signature: Signature = undefined;
3089
+ if (unionSignatures.length === 1 || source.typeParameters) {
3090
+ signature = source;
3091
+ }
3092
+ else {
3093
+ signature = cloneSignature(source);
3094
+ // Clear resolved return type we possibly got from cloneSignature
3095
+ signature.resolvedReturnType = undefined;
3096
+ signature.unionSignatures = unionSignatures;
3097
+ }
3098
+ (result || (result = [])).push(signature);
3079
3099
}
3080
3100
}
3081
- let result = map(signatures, cloneSignature);
3082
- for (var i = 0; i < result.length; i++) {
3083
- let s = result[i];
3084
- // Clear resolved return type we possibly got from cloneSignature
3085
- s.resolvedReturnType = undefined;
3086
- s.unionSignatures = map(signatureLists, signatures => signatures[i]);
3087
- }
3088
- return result;
3101
+ return result || emptyArray;
3089
3102
}
3090
3103
3091
3104
function getUnionIndexType(types: Type[], kind: IndexKind): Type {
@@ -3245,9 +3258,6 @@ namespace ts {
3245
3258
* type itself. Note that the apparent type of a union type is the union type itself.
3246
3259
*/
3247
3260
function getApparentType(type: Type): Type {
3248
- if (type.flags & TypeFlags.Union) {
3249
- type = getReducedTypeOfUnionType(<UnionType>type);
3250
- }
3251
3261
if (type.flags & TypeFlags.TypeParameter) {
3252
3262
do {
3253
3263
type = getConstraintOfTypeParameter(<TypeParameter>type);
@@ -4104,47 +4114,6 @@ namespace ts {
4104
4114
return type;
4105
4115
}
4106
4116
4107
- function isTypeSubtypeOfSomeType(candidate: Type, types: Type[]): boolean {
4108
- for (let type of types) {
4109
- if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
4110
- return true;
4111
- }
4112
- }
4113
- return false;
4114
- }
4115
-
4116
- function removeSubtypes(types: Type[]): Type[] {
4117
- let result = types;
4118
- let i = result.length;
4119
- while (i > 0) {
4120
- i--;
4121
- if (isTypeSubtypeOfSomeType(result[i], result)) {
4122
- if (result === types) {
4123
- result = types.slice(0);
4124
- }
4125
- result.splice(i, 1);
4126
- }
4127
- }
4128
- return result;
4129
- }
4130
-
4131
- // The reduced type is a union type in which no constituent type is a subtype of another
4132
- // constituent type.
4133
- function getReducedTypeOfUnionType(type: UnionType): Type {
4134
- if (!type.reducedType) {
4135
- type.reducedType = circularType;
4136
- let typesWithoutSubtypes = removeSubtypes(type.types);
4137
- let reducedType = typesWithoutSubtypes === type.types ? type : getUnionType(typesWithoutSubtypes);
4138
- if (type.reducedType === circularType) {
4139
- type.reducedType = reducedType;
4140
- }
4141
- }
4142
- else if (type.reducedType === circularType) {
4143
- type.reducedType = type;
4144
- }
4145
- return type.reducedType;
4146
- }
4147
-
4148
4117
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
4149
4118
let links = getNodeLinks(node);
4150
4119
if (!links.resolvedType) {
0 commit comments