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

Add the computed types debugger #47747

Closed
5 tasks done
kettanaito opened this issue Feb 5, 2022 · 4 comments
Closed
5 tasks done

Add the computed types debugger #47747

kettanaito opened this issue Feb 5, 2022 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@kettanaito
Copy link

kettanaito commented Feb 5, 2022

Suggestion

πŸ” Search Terms

  • debugger
  • computed
  • tooling

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

I suggest adding a computed types debugger to the TypeScript tooling.

The fact that there are 0 means to debug type-related issues is one objective downside of TypeScript that I constantly hear people complaining about. Any medium to high type complexity becomes impossible not only to debug but even to preview in the IDE. Autosuggestion popups are somewhat useful, however, they have a few issues:

  1. Feasible for rather simple types (i.e. type A = string);
  2. More complex type relations, like multiple-level nested generics, won't even fit the popup.
  3. Popup displays declaration values, not the computed values. For example, you see a: MyInterface<string> instead of the actual computed value of MyInterface<string>. I'd argue that the latter is much more useful during debugging, as you can see the type declaration for a but you can never see what TypeScript computes it to in the end.

There are existing open discussions on StackOverflow and even a code snippet that allows you to preview the computed types by cloning and modifying the typescript repo locally. There are some rather disruptive approaches to do something I'm convinced TypeScript should do natively. Yet, the existence of such approaches proves it is possible to preview the computed types in some way, and I'd kindly ask you to consider adding such ability to the TypeScript tooling.

API

This suggestion can be implemented in multiple ways but all of them require some changes to the checker.ts, or dependent code on the TypeScript side.

CLI flag

By adding a --show-computed-types flag to the tsc CLI.

$ tsc --show-computed-types my-code.ts

my-code.ts:4:24 Computed "RecursiveQuerySelectorWhere" type to:
-> string[]

VS Code Extension

By creating a VS Code extension that'd allow you to set custom debugger points next to your type definitions. Whenever the TypeScript compiler reaches that line, the compiler stops and you see the computed value of the type on which the debugger is set.

Screen Shot 2022-02-05 at 13 55 05

In the example above, I want to see the computed value of the Partial<GetQueryFor<Value>> type (and its parent RecursiveQuerySelectorWhere type) so I know what is the end type TypeScript is using.

The actual disruption of compilation is not mandatory. In fact, I think in order to preview the computed types you have to complete the compilation. The end goal is to be able to statically see the computed types TypeScript produced.

πŸ“ƒ Motivating Example

This feature adds a debugger that saves you hours of blind fidgeting with type definitions. This is an unrivaled tool to help you debug type issues in complex types, like nested generics.

πŸ’» Use Cases

I'm experiencing an issue with my type structure which is rather complex. I know there's an issue on my side but I don't have the tooling to find where exactly that issue is. So what I do is I change the related types in a blind attempt to find at least some clue as to what is going wrong.

To be more precise, I know that this type should produce a union of X | null. When I make it do so, the dependent generic down the chain does not recognize it's being passed a nullable type. The type dependency in my declarations is as follows:

QuerySelector <- the computed `Value` as generic input
- QuerySelectorWhere
  - RecursiveQuerySelectorWhere
    - GetQueryFor
@kettanaito
Copy link
Author

kettanaito commented Feb 5, 2022

As a reference, we can take a look at the Flow's Run-time Types. I think their approach is rather brilliant, where you use a designated helper type Type and assign it to actual runtime variables.

const user: Type = Type<MyComplexGeneric<string>>

Upon compilation, you're able to see the type of the user variable to debug it.

At the same time, it's important to have native compiler support for this. I wouldn't suggest using third-party tooling like illustrated here, because you will inevitably come to the point where the tooling itself deviates from the compiler or introduces issues on its own. For the lack of the native TS support for this, such third-party tools go into the extremity of re-mapping the typings to the runtime constructs:

import { T } from 'tool'

const user = {
  property: T.string
}

Not only this is limiting in nature, but it's also an extra effort to debug the types.

As I'm approaching this suggestion from the perspective of debugging complex structures, any intermediate chains in the form of third-party tooling will only increase that complexity.

@MartinJohns
Copy link
Contributor

Sounds like a duplicate of #30396.

@kettanaito
Copy link
Author

@MartinJohns, seems so. The only difference is the suggestions I'm posting above (#30396 has no opinion when it comes to the possible API). I also suspect that this suggestion may be less work than it seems, depending on the end solution we agree on.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Feb 7, 2022
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants