Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23276,11 +23276,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {

function getVariances(type: GenericType): VarianceFlags[] {
// Arrays and tuples are known to be covariant, no need to spend time computing this.
return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple ?
return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple || isArraySubtype(type) ?
arrayVariances :
getVariancesWorker(type.symbol, type.typeParameters);
}

/**
* If a type inherits from array, it also inherits the covariant type parameter variance, regardless of other type
* parameter usages (to allow overriding/writing new collection methods that are just as unsafe as the base array class).
*/
function isArraySubtype(type: GenericType): boolean {
return length(type.typeParameters) === 1 && length(getBaseTypes(type)) === 1
&& isTypeReferenceWithGenericArguments(getBaseTypes(type)[0])
&& getVariances((getBaseTypes(type)[0] as TypeReference).target) === arrayVariances
&& length(getTypeArguments(getBaseTypes(type)[0] as TypeReference)) === 1
&& getTypeArguments(getBaseTypes(type)[0] as TypeReference)[0] === type.typeParameters![0];
}

function getAliasVariances(symbol: Symbol) {
return getVariancesWorker(symbol, getSymbolLinks(symbol).typeParameters);
}
Expand Down