Skip to content
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

More flexible handling of circular types with "typeof function" inference #58616

Closed
6 tasks done
finom opened this issue May 22, 2024 · 6 comments · Fixed by #58650
Closed
6 tasks done

More flexible handling of circular types with "typeof function" inference #58616

finom opened this issue May 22, 2024 · 6 comments · Fixed by #58650
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases

Comments

@finom
Copy link

finom commented May 22, 2024

🔍 Search Terms

"is referenced directly or indirectly in its own type annotation.ts(2502)"
"self-referencing types"
"circular types"
...

✅ Viability Checklist

⭐ Suggestion

I would like to be able to infer type of a function A that calls another function B, returning its value, relying on parameters of function A (not sure if the description is good, see the code snippet).

📃 Motivating Example

function foo(arg: Parameters<typeof bar>[0]) {
  return arg;
}

function bar(arg: string) {
  return foo(arg);
}
image

The code above, obviously, would be unable to infer return type. But hypothetically it's possible to extract its parameters.

💻 Use Cases

More flexible type inference. Currently there is no workaround for this problem. My personal use-case is to produce less types while I define service and controller for my back-end. I've simplified the code to remove unnecessary types.

class ReportController {
  static createReport(body: { reportName: string }) {
    return ReportService.createReport(body);
  }
}

class ReportService {
  static createReport(body: Parameters<typeof ReportController.createReport>[0]) { // body is "any" + error
    // ...
  }
}

At this case body is clearly { reportName: string } but because of the restriction I'm not able to use it. At this example I can move body to a type variable but in practice it's more complicated because of other inferences and I would need to define body type for each controller method outside of the classes.

@fatcerberus
Copy link

I would like to be able to infer type of a function A that calls another function B, returning its value, relying on parameters of function A (not sure if the description is good, see the code snippet).

I'm not 100% sure, but based on your description I think you're looking for #40179?

@finom
Copy link
Author

finom commented May 22, 2024

@fatcerberus I think I'd still need to refer to the function type: paramsof typeof bar what would cause the same problem.

@ahejlsberg ahejlsberg self-assigned this May 24, 2024
@ahejlsberg ahejlsberg added Bug A bug in TypeScript Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases labels May 24, 2024
@ahejlsberg
Copy link
Member

ahejlsberg commented May 24, 2024

This is sort of a bug, but really more of a possible improvement. At any rate, during type inference in the instantiation of the Parameters<T> conditional type, we attempt to resolve the return type of bar without really needing to, which leads to a circularity. It's a pretty easy fix, I'll put up a PR.

@finom
Copy link
Author

finom commented May 24, 2024

@ahejlsberg that's amazing! Honestly, I didn't expect to get this reaction seeing so many issues at this repo ❤️

@finom
Copy link
Author

finom commented Jun 4, 2024

@ahejlsberg that's perfect! Thank you! I think many people would be happy to show their appreciation to you by sponsoring but unfortunately your sponsoring page is not set up. This update changes a lot in my code and solves a problem that I was having for very long time. Sorry for delayed reply, I didn't know how TS versioning works and just installed the PR version ❤️

@finom
Copy link
Author

finom commented Jun 5, 2024

@ahejlsberg I'm doing some tests but still getting similar problems. Could you also check the following and more complex example:

function withSchmuck<T, R>(arg: T, handler: (arg2: T) => R) {
  console.log(arg);
  return handler;
}

const foo = withSchmuck('hello', (arg) => {
  return bar(arg);
});

function bar(arg: Parameters<typeof foo>[0]) {
   console.log(arg);
}

The arg of bar should have type of string but TS says this is the same error as I got before. As in the previous case, nothing is trying to infer the return type, only arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Possible Improvement The current behavior isn't wrong, but it's possible to see that it might be better in some cases
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants