-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Add missing type argument constraints check #51766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/compiler/checker.ts
Outdated
| return getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias | ||
| } | ||
| else { | ||
| tryGetDeclaredTypeOfSymbol(resolvedSymbol); // call this first to ensure typeParameters is populated (if applicable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason you can't inspect the type returned from tryGetDeclaredTypeOfSymbol for type parameters? Or are TypeParameters only available only on Symbol(Links) instead of type references?
tryGetDeclaredTypeOfSymbol(resolvedSymbol).typeParameters would work, I think, if you check that the type is an InterfaceType (getObjectFlags(t) & (ObjectFlags.Class | ObjectFlags.Interface)) and that typeParameters is not undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason you can't inspect the type returned from tryGetDeclaredTypeOfSymbol for type parameters? Or are TypeParameters only available only on Symbol(Links) instead of type references?
So I tried the approach that you suggested and I observed that the type returned by tryGetDeclaredTypeOfSymbol() is not InterfaceType but TypeReference, where target is InterfaceType. When I try target.typeParameters, this unfortunately doesn't work because the elements of target.typeParameters do not have constraint property for some reason.
Next, I examined other uses of checkTypeArgumentConstraint() and it seems like typeParameters are obtained via getTypeParametersForTypeReference(). When you check the implementation of that function, it seems to be conceptually equivalent to what I was doing (it uses getSymbolLinks() at the end of the day):
function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) {
const type = getTypeFromTypeReference(node);
if (!isErrorType(type)) {
const symbol = getNodeLinks(node).resolvedSymbol;
if (symbol) {
return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters ||
(getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target.localTypeParameters : undefined);
}
}
return undefined;
}So I ended up extracting a getTypeParametersForTypeAndSymbol() sub-routine in order to leverage the same logic for handling edge cases. Does that make more sense to you now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, extracting the existing code seems like a good solution.
sandersn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can get typeParameters more directly.
src/compiler/checker.ts
Outdated
| return getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias | ||
| } | ||
| else { | ||
| tryGetDeclaredTypeOfSymbol(resolvedSymbol); // call this first to ensure typeParameters is populated (if applicable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, extracting the existing code seems like a good solution.
Fixes #29530
Normally the argument constraints check would be executed via
checkTypeReferenceNode()but since an expression of the formimport(...).Type<A, B, C>yieldsSyntaxKind.ImportTyperather thanSyntaxKind.TypeReference, this is not happening. I was trying to find a place in the code where this validation could be added, which would be as close tocheckImportType()as possible and it would not require any major refactoring. This is how I landed atresolveImportSymbolType(), but I am not sure if it's the best possible choice.My guts feeling is that I should be able to perform a similar check using the type evaluated with
getTypeReferenceType(), and so the constraints validation could potentially be encapsulated withincheckImportType(), which I think would be more appropriate. I'd appreciate any piece of advise on this matter.