@@ -43,8 +43,6 @@ namespace ts {
4343 let emptyArray: any[] = [];
4444 let emptySymbols: SymbolTable = {};
4545
46- let jsxElementClassType: Type = undefined;
47-
4846 let compilerOptions = host.getCompilerOptions();
4947 let languageVersion = compilerOptions.target || ScriptTarget.ES3;
5048 let modulekind = compilerOptions.module ? compilerOptions.module : languageVersion === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.None;
@@ -4940,6 +4938,9 @@ namespace ts {
49404938 }
49414939 return objectTypeRelatedTo(<ObjectType>source, <ObjectType>target, /*reportErrors*/ false);
49424940 }
4941+ if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
4942+ return typeParameterIdenticalTo(<TypeParameter>source, <TypeParameter>target);
4943+ }
49434944 if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
49444945 source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
49454946 if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
@@ -5070,6 +5071,20 @@ namespace ts {
50705071 return result;
50715072 }
50725073
5074+ function typeParameterIdenticalTo(source: TypeParameter, target: TypeParameter): Ternary {
5075+ if (source.symbol.name !== target.symbol.name) {
5076+ return Ternary.False;
5077+ }
5078+ // covers case when both type parameters does not have constraint (both equal to noConstraintType)
5079+ if (source.constraint === target.constraint) {
5080+ return Ternary.True;
5081+ }
5082+ if (source.constraint === noConstraintType || target.constraint === noConstraintType) {
5083+ return Ternary.False;
5084+ }
5085+ return isIdenticalTo(source.constraint, target.constraint);
5086+ }
5087+
50735088 // Determine if two object types are related by structure. First, check if the result is already available in the global cache.
50745089 // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true.
50755090 // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
@@ -5592,20 +5607,27 @@ namespace ts {
55925607 return Ternary.False;
55935608 }
55945609 }
5595- // Check that the two signatures have the same number of type parameters. We might consider
5596- // also checking that any type parameter constraints match, but that would require instantiating
5597- // the constraints with a common set of type arguments to get relatable entities in places where
5598- // type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile,
5599- // particularly as we're comparing erased versions of the signatures below.
5600- if ((source.typeParameters ? source.typeParameters.length : 0) !== (target.typeParameters ? target.typeParameters.length : 0)) {
5610+ let result = Ternary.True;
5611+ if (source.typeParameters && target.typeParameters) {
5612+ if (source.typeParameters.length !== target.typeParameters.length) {
5613+ return Ternary.False;
5614+ }
5615+ for (let i = 0, len = source.typeParameters.length; i < len; ++i) {
5616+ let related = compareTypes(source.typeParameters[i], target.typeParameters[i]);
5617+ if (!related) {
5618+ return Ternary.False;
5619+ }
5620+ result &= related;
5621+ }
5622+ }
5623+ else if (source.typeParameters || target.typeParameters) {
56015624 return Ternary.False;
56025625 }
56035626 // Spec 1.0 Section 3.8.3 & 3.8.4:
56045627 // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
56055628 source = getErasedSignature(source);
56065629 target = getErasedSignature(target);
5607- let result = Ternary.True;
5608- const targetLen = target.parameters.length;
5630+ let targetLen = target.parameters.length;
56095631 for (let i = 0; i < targetLen; i++) {
56105632 let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
56115633 let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
@@ -5906,17 +5928,6 @@ namespace ts {
59065928 }
59075929
59085930 function inferFromTypes(source: Type, target: Type) {
5909- if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
5910- source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
5911- // Source and target are both unions or both intersections. To improve the quality of
5912- // inferences we first reduce the types by removing constituents that are identically
5913- // matched by a constituent in the other type. For example, when inferring from
5914- // 'string | string[]' to 'string | T', we reduce the types to 'string[]' and 'T'.
5915- const reducedSource = reduceUnionOrIntersectionType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
5916- const reducedTarget = reduceUnionOrIntersectionType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
5917- source = reducedSource;
5918- target = reducedTarget;
5919- }
59205931 if (target.flags & TypeFlags.TypeParameter) {
59215932 // If target is a type parameter, make an inference, unless the source type contains
59225933 // the anyFunctionType (the wildcard type that's used to avoid contextually typing functions).
@@ -5927,7 +5938,8 @@ namespace ts {
59275938 if (source.flags & TypeFlags.ContainsAnyFunctionType) {
59285939 return;
59295940 }
5930- const typeParameters = context.typeParameters;
5941+
5942+ let typeParameters = context.typeParameters;
59315943 for (let i = 0; i < typeParameters.length; i++) {
59325944 if (target === typeParameters[i]) {
59335945 let inferences = context.inferences[i];
@@ -5999,9 +6011,12 @@ namespace ts {
59996011 }
60006012 else {
60016013 source = getApparentType(source);
6002- if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) ||
6003- (target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
6004- // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members
6014+ if (source.flags & TypeFlags.ObjectType && (
6015+ target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
6016+ target.flags & TypeFlags.Tuple ||
6017+ target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
6018+ // If source is an object type, and target is a type reference with type arguments, a tuple type,
6019+ // the type of a method, or a type literal, infer from members
60056020 if (isInProcess(source, target)) {
60066021 return;
60076022 }
@@ -6074,41 +6089,6 @@ namespace ts {
60746089 }
60756090 }
60766091
6077- function typeIdenticalToSomeType(source: Type, target: UnionOrIntersectionType): boolean {
6078- for (const t of target.types) {
6079- if (isTypeIdenticalTo(source, t)) {
6080- return true;
6081- }
6082- }
6083- return false;
6084- }
6085-
6086- /**
6087- * Return the reduced form of the source type. This type is computed by by removing all source
6088- * constituents that have an identical match in the target type.
6089- */
6090- function reduceUnionOrIntersectionType(source: UnionOrIntersectionType, target: UnionOrIntersectionType) {
6091- let sourceTypes = source.types;
6092- let sourceIndex = 0;
6093- let modified = false;
6094- while (sourceIndex < sourceTypes.length) {
6095- if (typeIdenticalToSomeType(sourceTypes[sourceIndex], target)) {
6096- if (!modified) {
6097- sourceTypes = sourceTypes.slice(0);
6098- modified = true;
6099- }
6100- sourceTypes.splice(sourceIndex, 1);
6101- }
6102- else {
6103- sourceIndex++;
6104- }
6105- }
6106- if (modified) {
6107- return source.flags & TypeFlags.Union ? getUnionType(sourceTypes, /*noSubtypeReduction*/ true) : getIntersectionType(sourceTypes);
6108- }
6109- return source;
6110- }
6111-
61126092 function getInferenceCandidates(context: InferenceContext, index: number): Type[] {
61136093 let inferences = context.inferences[index];
61146094 return inferences.primary || inferences.secondary || emptyArray;
@@ -7882,6 +7862,7 @@ namespace ts {
78827862 return prop || unknownSymbol;
78837863 }
78847864
7865+ let jsxElementClassType: Type = undefined;
78857866 function getJsxGlobalElementClassType(): Type {
78867867 if (!jsxElementClassType) {
78877868 jsxElementClassType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.ElementClass);
0 commit comments