-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Avoid listing missing properties on types with only call/construct signatures #35735
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
Comments
Hm, OK, but suppose interface Dog {
caller: {
caller: {
collar: boolean;
};
}
}
declare function getRover(): Dog;
export let x: Dog = getRover; for which we issue
what's the rule here? In the above example, I can't make a clear judgement call on which suggestion is more relevant. |
If you are in the off case where you have a |
When the return type of a function is an identity match for the target type, it seems extremely unlikely that "You forgot to call it?" is not the best possible error message. It requires a lot of construction to make something where a function and its return type are both plausible matches for the target. I would be curious to find out how often a function is ever an intentional source for a target with zero signatures that isn't a top-ish type. Even assigning a function to something nominally uncontroversial like |
I've seen assignments to |
Does this still need help? I would like to work on this. |
Yes, we're still looking for help here! |
Ok, I'll work on this! |
I think the fix should be relatively self-contained within // Even if relationship doesn't hold for unions, intersections, or generic type references,
// it may hold in a structural comparison.
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
// relates to X. Thus, we include intersection types on the source side here.
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
// Report structural errors only if we haven't reported any errors yet
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo.errorInfo && !sourceIsPrimitive;
result = propertiesRelatedTo(source, target, reportStructuralErrors, /*excludedProperties*/ undefined, intersectionState);
if (result) {
result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors);
if (result) {
result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors);
if (result) {
result &= indexTypesRelatedTo(source, target, IndexKind.String, sourceIsPrimitive, reportStructuralErrors, intersectionState);
if (result) {
result &= indexTypesRelatedTo(source, target, IndexKind.Number, sourceIsPrimitive, reportStructuralErrors, intersectionState);
}
}
} |
Hi, I'm new here and would like to give this a try. Would anyone mind if I started working on this? |
@liewrichmond go for it! 👍 |
I've been working on a fix, and I think I might have one but it breaks a couple of tests that I'm not too sure if it's intended behavior or not. For example, interface Dog {
barkable: true
}
declare function getRover(): Dog
let x: any[] = []
x = getRover; Before Change
After Change
Is this within spec? and should I submit a PR to get feedback/suggestions on the other failing tests due to the change? |
Yeah, that looks good. You can send a PR and we should be able to iterate on it. |
…all/construct signatures (#40973) * Fixes #35735 * fixes #35735 * PR feedback Co-authored-by: Wesley Wigham <[email protected]>
Thank you @liewrichmond! |
Found with @RyanCavanaugh
Expected
Actual
The text was updated successfully, but these errors were encountered: