Description
Suggestion
When a class implements an interface or extends a base class (esp. a class type defined in the package's .d.ts), then there should be an easy way for IDE users to add type annotations to parameter types and return types for class methods that exist on the base type(s). Note that this is different (although related) to #23911 which is about inference. I'm talking here about enabling opt-in IDE actions, not automatic inference. An opt-in solution may avoid some of the edge cases and technical pitfalls that have prevented #23911 from being successful so far.
🔍 Search Terms
infer from usage
parameter types
return types
implements
base class
✅ 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
Currently, "infer from usage" for function parameters (does it infer return types too?) seems to ignore the type of that method in interfaces that are implemented by that class, or in base classes. It shouldn't! The base class or interface seems like it should be the most reliable indicator of "usage" and should either override or augment whatever type info TS can gather from usage.
Both parameter types and return types should be fetched from the base interface or class.
I know that there's work on inference (#23911 and elsewhere), but I'm asking for something simpler: an opt-in way for IDE users to add type annotations to their source code using the base class or interface type(s).
What makes #23911 hard are all the weird cases, like multiple inheritance, overloads, derived classes that intentionally vary signatures from its parent, etc.
But using an opt-in, IDE-centric solution could sidestep many of those annoying corner cases by simply bailing out when those edge cases happen, or providing a "best effort" output that the user can reject with Ctrl-Z/CMD+Z if they don't like it.
I'm not sure whether this feature should be a refactoring, part of "infer from usage", or both.
It'd be ideal if there were a way to do it for one method and also to do it for all methods in a type and/or in a file, because often when you want to fill in one method's parameter/return types, then you also need to fill in all of them!
Note that any support should include both base classes and base interfaces.
📃 Motivating Example
We are in the middle of porting the Stage 3 Temporal proposal polyfill to TS. It was painful to add types to hundreds of class methods that implemented abstract class types defined in our .d.ts. This seemed like completely unnecessary manual gruntwork that could and should have been automated.
I also committed bugs in the process. For example, I accidentally omitted a = undefined
default value on some parameters due to a mistake in the search-n-replace regex I was using to add parameter types.
I suspect that these are common problems any time a JS codebase is migrated to TS.
If there were an automated way to overlay the base class types on an existing implementation, it would have saved our team ~20 hours.
💻 Use Cases
The main use case I'm familiar with is porting a JS codebase to TS. Nowadays most JS packages have an existing .d.ts that defines the public API, so it'd be great to be able to use that to jumpstart the migration of the implementation to TS.
The best workaround I've found so far is to create some generic types (e.g. PlainDateParams<T extends keyof PlainDate>
and PlainDateReturn<T extends keyof PlainDate
) that define parameters and return types of class methods (including statics and constructors), and then use regex search-and-replace to look for method parameters that lack types, and use $1, $2, etc. to add XxxParams
and XxxReturn
annotations to them. This is better than completely manual work, but it's still time-consuming and error prone (e.g. when there are inline comments, default values, line breaks, etc.)