Skip to content

Commit 8abf6e5

Browse files
committed
Properly exclude 'this' type arguments
1 parent ed4e812 commit 8abf6e5

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

src/compiler/checker.ts

+24-19
Original file line numberDiff line numberDiff line change
@@ -12537,6 +12537,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1253712537
return needApparentType ? getApparentType(type) : type;
1253812538
}
1253912539

12540+
function getThisArgument(type: Type) {
12541+
return getObjectFlags(type) & ObjectFlags.Reference && length(getTypeArguments(type as TypeReference)) > getTypeReferenceArity(type as TypeReference) ? last(getTypeArguments(type as TypeReference)) : type;
12542+
}
12543+
1254012544
function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: readonly TypeParameter[], typeArguments: readonly Type[]) {
1254112545
let mapper: TypeMapper | undefined;
1254212546
let members: SymbolTable;
@@ -12666,7 +12670,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1266612670
return [sig.parameters];
1266712671

1266812672
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
12669-
const elementTypes = getTypeArguments(restType);
12673+
const elementTypes = getElementTypes(restType);
1267012674
const associatedNames = getUniqAssociatedNamesFromTupleType(restType);
1267112675
const restParams = map(elementTypes, (t, i) => {
1267212676
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
@@ -13564,7 +13568,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1356413568
type.flags & TypeFlags.IndexedAccess && isConstTypeVariable((type as IndexedAccessType).objectType) ||
1356513569
type.flags & TypeFlags.Conditional && isConstTypeVariable(getConstraintOfConditionalType(type as ConditionalType)) ||
1356613570
type.flags & TypeFlags.Substitution && isConstTypeVariable((type as SubstitutionType).baseType) ||
13567-
isGenericTupleType(type) && findIndex(getTypeArguments(type), (t, i) => !!(type.target.elementFlags[i] & ElementFlags.Variadic) && isConstTypeVariable(t)) >= 0));
13571+
isGenericTupleType(type) && findIndex(getElementTypes(type), (t, i) => !!(type.target.elementFlags[i] & ElementFlags.Variadic) && isConstTypeVariable(t)) >= 0));
1356813572
}
1356913573

1357013574
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
@@ -13718,7 +13722,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1371813722
return type.resolvedBaseConstraint;
1371913723
}
1372013724
const stack: object[] = [];
13721-
return type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type);
13725+
return type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), getThisArgument(type));
1372213726

1372313727
function getImmediateBaseConstraint(t: Type): Type {
1372413728
if (!t.immediateBaseConstraint) {
@@ -13821,12 +13825,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1382113825
return getBaseConstraint(getSubstitutionIntersection(t as SubstitutionType));
1382213826
}
1382313827
if (isGenericTupleType(t)) {
13824-
// We substitute constrains for variadic elements only when the constrains are array or tuple types
13825-
// as we want to avoid further (possibly unbounded) recursion.
13826-
const newElements = map(getTypeArguments(t), (v, i) => {
13827-
const constraint = t.target.elementFlags[i] & ElementFlags.Variadic ? getBaseConstraint(v) : undefined;
13828-
return constraint && everyType(constraint, isArrayOrTupleType) ? constraint : v;
13829-
});
13828+
const newElements = map(getElementTypes(t), (v, i) => t.target.elementFlags[i] & ElementFlags.Variadic && getBaseConstraint(v) || v);
1383013829
return createTupleType(newElements, t.target.elementFlags, t.target.readonly, t.target.labeledElementDeclarations);
1383113830
}
1383213831
return t;
@@ -16136,7 +16135,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1613616135
addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]);
1613716136
}
1613816137
else if (isTupleType(type)) {
16139-
const elements = getTypeArguments(type);
16138+
const elements = getElementTypes(type);
1614016139
if (elements.length + expandedTypes.length >= 10_000) {
1614116140
error(currentNode, isPartOfTypeNode(currentNode!)
1614216141
? Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent
@@ -16218,6 +16217,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1621816217
return type.elementFlags.length - findLastIndex(type.elementFlags, f => !(f & flags)) - 1;
1621916218
}
1622016219

16220+
function getElementTypes(type: TupleTypeReference): readonly Type[] {
16221+
const typeArguments = getTypeArguments(type);
16222+
const arity = getTypeReferenceArity(type);
16223+
return typeArguments.length === arity ? typeArguments : typeArguments.slice(0, arity);
16224+
}
16225+
1622116226
function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type {
1622216227
return addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true);
1622316228
}
@@ -17746,7 +17751,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1774617751
}
1774717752

1774817753
function isDeferredType(type: Type, checkTuples: boolean) {
17749-
return isGenericType(type) || checkTuples && isTupleType(type) && some(getTypeArguments(type), isGenericType);
17754+
return isGenericType(type) || checkTuples && isTupleType(type) && some(getElementTypes(type), isGenericType);
1775017755
}
1775117756

1775217757
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
@@ -18885,7 +18890,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1888518890
// M<[A, B?, ...T, ...C[]] into [...M<[A]>, ...M<[B?]>, ...M<T>, ...M<C[]>] and then rely on tuple type
1888618891
// normalization to resolve the non-generic parts of the resulting tuple.
1888718892
const elementFlags = tupleType.target.elementFlags;
18888-
const elementTypes = map(getTypeArguments(tupleType), (t, i) => {
18893+
const elementTypes = map(getElementTypes(tupleType), (t, i) => {
1888918894
const singleton = elementFlags[i] & ElementFlags.Variadic ? t :
1889018895
elementFlags[i] & ElementFlags.Rest ? createArrayType(t) :
1889118896
createTupleType([t], [elementFlags[i]]);
@@ -18904,7 +18909,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1890418909

1890518910
function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) {
1890618911
const elementFlags = tupleType.target.elementFlags;
18907-
const elementTypes = map(getTypeArguments(tupleType), (_, i) =>
18912+
const elementTypes = map(getElementTypes(tupleType), (_, i) =>
1890818913
instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ElementFlags.Optional), mapper));
1890918914
const modifiers = getMappedTypeModifiers(mappedType);
1891018915
const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) :
@@ -20209,7 +20214,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2020920214
}
2021020215

2021120216
function getNormalizedTupleType(type: TupleTypeReference, writing: boolean): Type {
20212-
const elements = getTypeArguments(type);
20217+
const elements = getElementTypes(type);
2021320218
const normalizedElements = sameMap(elements, t => t.flags & TypeFlags.Simplifiable ? getSimplifiedType(t, writing) : t);
2021420219
return elements !== normalizedElements ? createNormalizedTupleType(type.target, normalizedElements) : type;
2021520220
}
@@ -24043,7 +24048,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2404324048
function isPartiallyInferableType(type: Type): boolean {
2404424049
return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) ||
2404524050
isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) ||
24046-
isTupleType(type) && some(getTypeArguments(type), isPartiallyInferableType);
24051+
isTupleType(type) && some(getElementTypes(type), isPartiallyInferableType);
2404724052
}
2404824053

2404924054
function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) {
@@ -24058,7 +24063,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2405824063
return createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source));
2405924064
}
2406024065
if (isTupleType(source)) {
24061-
const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
24066+
const elementTypes = map(getElementTypes(source), t => inferReverseMappedType(t, target, constraint));
2406224067
const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
2406324068
sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) :
2406424069
source.target.elementFlags;
@@ -32398,7 +32403,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3239832403
function getMutableArrayOrTupleType(type: Type) {
3239932404
return type.flags & TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) :
3240032405
type.flags & TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type :
32401-
isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.elementFlags, /*readonly*/ false, type.target.labeledElementDeclarations) :
32406+
isTupleType(type) ? createTupleType(getElementTypes(type), type.target.elementFlags, /*readonly*/ false, type.target.labeledElementDeclarations) :
3240232407
createTupleType([type], [ElementFlags.Variadic]);
3240332408
}
3240432409

@@ -32732,7 +32737,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3273232737
// We can call checkExpressionCached because spread expressions never have a contextual type.
3273332738
const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) : checkExpressionCached((arg as SpreadElement).expression));
3273432739
if (spreadType && isTupleType(spreadType)) {
32735-
forEach(getTypeArguments(spreadType), (t, i) => {
32740+
forEach(getElementTypes(spreadType), (t, i) => {
3273632741
const flags = spreadType.target.elementFlags[i];
3273732742
const syntheticArg = createSyntheticExpression(arg, flags & ElementFlags.Rest ? createArrayType(t) : t,
3273832743
!!(flags & ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]);
@@ -37342,7 +37347,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3734237347

3734337348
function padTupleType(type: TupleTypeReference, pattern: ArrayBindingPattern) {
3734437349
const patternElements = pattern.elements;
37345-
const elementTypes = getTypeArguments(type).slice();
37350+
const elementTypes = getElementTypes(type).slice();
3734637351
const elementFlags = type.target.elementFlags.slice();
3734737352
for (let i = getTypeReferenceArity(type); i < patternElements.length; i++) {
3734837353
const e = patternElements[i];

0 commit comments

Comments
 (0)