@@ -7636,35 +7636,35 @@ namespace ts {
7636
7636
* @param typeParameters The requested type parameters.
7637
7637
* @param minTypeArgumentCount The minimum number of required type arguments.
7638
7638
*/
7639
- function fillMissingTypeArguments(typeArguments: Type[] , typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
7640
- function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
7641
- function fillMissingTypeArguments(typeArguments: Type[] | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
7639
+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> , typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[];
7640
+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined;
7641
+ function fillMissingTypeArguments(typeArguments: ReadonlyArray< Type> | undefined, typeParameters: ReadonlyArray<TypeParameter> | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) {
7642
7642
const numTypeParameters = length(typeParameters);
7643
- if (numTypeParameters) {
7644
- const numTypeArguments = length(typeArguments) ;
7645
- if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
7646
- if (! typeArguments) {
7647
- typeArguments = [];
7648
- }
7643
+ if (! numTypeParameters) {
7644
+ return [] ;
7645
+ }
7646
+ const numTypeArguments = length( typeArguments);
7647
+ if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) {
7648
+ const result = typeArguments ? typeArguments.slice() : [];
7649
7649
7650
- // Map an unsatisfied type parameter with a default type.
7651
- // If a type parameter does not have a default type, or if the default type
7652
- // is a forward reference, the empty object type is used.
7653
- for (let i = numTypeArguments; i < numTypeParameters; i++) {
7654
- typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7655
- }
7656
- for (let i = numTypeArguments; i < numTypeParameters; i++) {
7657
- const mapper = createTypeMapper(typeParameters!, typeArguments);
7658
- let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
7659
- if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
7660
- defaultType = anyType;
7661
- }
7662
- typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7650
+ // Map an unsatisfied type parameter with a default type.
7651
+ // If a type parameter does not have a default type, or if the default type
7652
+ // is a forward reference, the empty object type is used.
7653
+ for (let i = numTypeArguments; i < numTypeParameters; i++) {
7654
+ result[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny);
7655
+ }
7656
+ for (let i = numTypeArguments; i < numTypeParameters; i++) {
7657
+ const mapper = createTypeMapper(typeParameters!, result);
7658
+ let defaultType = getDefaultFromTypeParameter(typeParameters![i]);
7659
+ if (isJavaScriptImplicitAny && defaultType && isTypeIdenticalTo(defaultType, emptyObjectType)) {
7660
+ defaultType = anyType;
7663
7661
}
7664
- typeArguments.length = typeParameters!.length ;
7662
+ result[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny) ;
7665
7663
}
7664
+ result.length = typeParameters!.length;
7665
+ return result;
7666
7666
}
7667
- return typeArguments;
7667
+ return typeArguments && typeArguments.slice() ;
7668
7668
}
7669
7669
7670
7670
function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature {
@@ -8262,7 +8262,7 @@ namespace ts {
8262
8262
return checkNoTypeArguments(node, symbol) ? type : errorType;
8263
8263
}
8264
8264
8265
- function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[] | undefined): Type {
8265
+ function getTypeAliasInstantiation(symbol: Symbol, typeArguments: ReadonlyArray< Type> | undefined): Type {
8266
8266
const type = getDeclaredTypeOfSymbol(symbol);
8267
8267
const links = getSymbolLinks(symbol);
8268
8268
const typeParameters = links.typeParameters!;
@@ -11783,9 +11783,7 @@ namespace ts {
11783
11783
return result;
11784
11784
}
11785
11785
11786
- function typeArgumentsRelatedTo(source: TypeReference, target: TypeReference, variances: Variance[], reportErrors: boolean): Ternary {
11787
- const sources = source.typeArguments || emptyArray;
11788
- const targets = target.typeArguments || emptyArray;
11786
+ function typeArgumentsRelatedTo(sources: ReadonlyArray<Type> = emptyArray, targets: ReadonlyArray<Type> = emptyArray, variances: ReadonlyArray<Variance> = emptyArray, reportErrors: boolean): Ternary {
11789
11787
if (sources.length !== targets.length && relation === identityRelation) {
11790
11788
return Ternary.False;
11791
11789
}
@@ -11938,9 +11936,25 @@ namespace ts {
11938
11936
}
11939
11937
return Ternary.False;
11940
11938
}
11939
+
11941
11940
let result: Ternary;
11942
11941
let originalErrorInfo: DiagnosticMessageChain | undefined;
11943
11942
const saveErrorInfo = errorInfo;
11943
+
11944
+ // We limit alias variance probing to only object and conditional types since their alias behavior
11945
+ // is more predictable than other, interned types, which may or may not have an alias depending on
11946
+ // the order in which things were checked.
11947
+ if (source.flags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol &&
11948
+ source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol &&
11949
+ !(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) {
11950
+ const variances = getAliasVariances(source.aliasSymbol);
11951
+ if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) {
11952
+ return result;
11953
+ }
11954
+ originalErrorInfo = errorInfo;
11955
+ errorInfo = saveErrorInfo;
11956
+ }
11957
+
11944
11958
if (target.flags & TypeFlags.TypeParameter) {
11945
11959
// A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P].
11946
11960
if (getObjectFlags(source) & ObjectFlags.Mapped && getConstraintTypeFromMappedType(<MappedType>source) === getIndexType(target)) {
@@ -12101,7 +12115,7 @@ namespace ts {
12101
12115
// type references (which are intended by be compared structurally). Obtain the variance
12102
12116
// information for the type parameters and relate the type arguments accordingly.
12103
12117
const variances = getVariances((<TypeReference>source).target);
12104
- if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, variances, reportErrors)) {
12118
+ if (result = typeArgumentsRelatedTo(( <TypeReference>source).typeArguments, ( <TypeReference>target).typeArguments , variances, reportErrors)) {
12105
12119
return result;
12106
12120
}
12107
12121
// The type arguments did not relate appropriately, but it may be because we have no variance
@@ -12608,48 +12622,58 @@ namespace ts {
12608
12622
return result;
12609
12623
}
12610
12624
12625
+ function getAliasVariances(symbol: Symbol) {
12626
+ const links = getSymbolLinks(symbol);
12627
+ return getVariancesWorker(links.typeParameters, links, (_links, param, marker) => {
12628
+ const type = getTypeAliasInstantiation(symbol, instantiateTypes(links.typeParameters!, makeUnaryTypeMapper(param, marker)));
12629
+ type.aliasTypeArgumentsContainsMarker = true;
12630
+ return type;
12631
+ });
12632
+ }
12633
+
12611
12634
// Return an array containing the variance of each type parameter. The variance is effectively
12612
12635
// a digest of the type comparisons that occur for each type argument when instantiations of the
12613
12636
// generic type are structurally compared. We infer the variance information by comparing
12614
12637
// instantiations of the generic type for type arguments with known relations. The function
12615
12638
// returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function
12616
12639
// has been invoked recursively for the given generic type.
12640
+ function getVariancesWorker<TCache extends { variances?: Variance[] }>(typeParameters: ReadonlyArray<TypeParameter> = emptyArray, cache: TCache, createMarkerType: (input: TCache, param: TypeParameter, marker: Type) => Type): Variance[] {
12641
+ let variances = cache.variances;
12642
+ if (!variances) {
12643
+ // The emptyArray singleton is used to signal a recursive invocation.
12644
+ cache.variances = emptyArray;
12645
+ variances = [];
12646
+ for (const tp of typeParameters) {
12647
+ // We first compare instantiations where the type parameter is replaced with
12648
+ // marker types that have a known subtype relationship. From this we can infer
12649
+ // invariance, covariance, contravariance or bivariance.
12650
+ const typeWithSuper = createMarkerType(cache, tp, markerSuperType);
12651
+ const typeWithSub = createMarkerType(cache, tp, markerSubType);
12652
+ let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) |
12653
+ (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0);
12654
+ // If the instantiations appear to be related bivariantly it may be because the
12655
+ // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
12656
+ // type). To determine this we compare instantiations where the type parameter is
12657
+ // replaced with marker types that are known to be unrelated.
12658
+ if (variance === Variance.Bivariant && isTypeAssignableTo(createMarkerType(cache, tp, markerOtherType), typeWithSuper)) {
12659
+ variance = Variance.Independent;
12660
+ }
12661
+ variances.push(variance);
12662
+ }
12663
+ cache.variances = variances;
12664
+ }
12665
+ return variances;
12666
+ }
12667
+
12617
12668
function getVariances(type: GenericType): Variance[] {
12618
12669
if (!strictFunctionTypes) {
12619
12670
return emptyArray;
12620
12671
}
12621
- const typeParameters = type.typeParameters || emptyArray;
12622
- let variances = type.variances;
12623
- if (!variances) {
12624
- if (type === globalArrayType || type === globalReadonlyArrayType) {
12625
- // Arrays are known to be covariant, no need to spend time computing this
12626
- variances = [Variance.Covariant];
12627
- }
12628
- else {
12629
- // The emptyArray singleton is used to signal a recursive invocation.
12630
- type.variances = emptyArray;
12631
- variances = [];
12632
- for (const tp of typeParameters) {
12633
- // We first compare instantiations where the type parameter is replaced with
12634
- // marker types that have a known subtype relationship. From this we can infer
12635
- // invariance, covariance, contravariance or bivariance.
12636
- const typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType);
12637
- const typeWithSub = getMarkerTypeReference(type, tp, markerSubType);
12638
- let variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? Variance.Covariant : 0) |
12639
- (isTypeAssignableTo(typeWithSuper, typeWithSub) ? Variance.Contravariant : 0);
12640
- // If the instantiations appear to be related bivariantly it may be because the
12641
- // type parameter is independent (i.e. it isn't witnessed anywhere in the generic
12642
- // type). To determine this we compare instantiations where the type parameter is
12643
- // replaced with marker types that are known to be unrelated.
12644
- if (variance === Variance.Bivariant && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) {
12645
- variance = Variance.Independent;
12646
- }
12647
- variances.push(variance);
12648
- }
12649
- }
12650
- type.variances = variances;
12672
+ if (type === globalArrayType || type === globalReadonlyArrayType) {
12673
+ // Arrays are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
12674
+ return emptyArray;
12651
12675
}
12652
- return variances ;
12676
+ return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference) ;
12653
12677
}
12654
12678
12655
12679
// Return true if the given type reference has a 'void' type argument for a covariant type parameter.
0 commit comments