question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Refactor: Generate narrower type based on usage.

See original GitHub issue

Suggestion

🔍 Search Terms

  1. refactor
  2. type
  3. narrow
  4. generate
  5. interface
  6. decouple

✅ 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

A new refactor feature which creates a minimal interface based on usage for an argument.

📃 Motivating Example

Imagine we have created an interface, User.

interface User {
	id: string,
	created_at: Date,
	updated_at: Date
	name: string
	email: string
}

When we started with our project, we created some super fancy rendering table which shows a list of users by name, and when they were last_updated, and when they were created.

const renderTable = (data: User[])=> {
  return (
    <table>
      <thead> <th key={i.id}><td>name</td><td>created at</td><td>updated at</td></th></thead>
      <tbody>
        {data.map(i => <tr key={i.id}><td>{i.name}</td><td>{i.created_at}</td><td>{i.updated_at}</td></tr>)}
      </tbody>
    </table>
  )
} 

Then we decide to add books to our app.


interface Book {
   id: string
   name: string
   created_at: Date
   updated_at: Date
   last_checkout: {date: Date, user: User}
}

We want the same functionality for rendering books as we have for users. Luckily, renderTable is pretty re-usable. So we just add our interface to types for data:

const renderTable = (data: (User|Book)[])=> {
// ...

Then, we add Libraries, and repeat

const renderTable = (data: (User|Book|Library)[])=> {
// ...

We could keep adding to this list, but in order to avoid infinite joins, we might want to refactor this, so that the data type only specifies what it actually needs. So we create a generic interface, maybe called TableRenderable, which has all the properties we need to make the data renderable.

interface TableRenderable {
  id: string
  name: string
  created_at: Date
  updated_at: Date
}
const renderTable = (data: TableRenderable[]) => {

Nice, now we have a minimal interface that this table needs to be able to render the data.

That was easy enough, but imagine if table weren’t so simple, maybe it called half a dozen other functions, which all use the User interface, and had a few more than 3 properties.

In order to refactor, you would need to first go into each function, and create the minimal interface for each function, then on the renderTable function, create the minimal interface TableRenderable. This still isn’t that bad, but it is a bit time consuming.

Typescript can help by implementing a refactor feature Generate Minimal Interface. Typescript already has all the information needed in the function to know which properties are being used by this function, and what types the are. We just need to combine all that information into a new interface. Tedious for human beings, simple for a type system.

Now with the new feature, you can start with each function renderTable calls, replace the User type with a generated minimal interface. Then finally, in the renderTable function, create the TableRenderable interface.

Instead of 10+ minutes in many of my real use cases, decoupling functions from the User interface could take a minute or 2.

💻 Use Cases

What do you want to use this for?

Decoupling interfaces from functions much more quickly.

What shortcomings exist with current approaches?

Decoupling in this manner is manual, as far as I am aware, which is ok, but it’s something that a computer could do just as easily.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:3
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
RyanCavanaughcommented, May 25, 2022

@ericwooley no, AMF is sort of the default state for suggestions that don’t need design work but don’t currently meet the bar for adding to the codebase

0reactions
ericwooleycommented, May 25, 2022

@RyanCavanaugh Is there anything I need to add to get past the “Awaiting More Feedback” label?

Read more comments on GitHub >

github_iconTop Results From Across the Web

What's the best way to refactor a method that has too many (6+ ...
If you have that many parameters, chances are that the method is doing too much, so address this first by splitting the method...
Read more >
Refactor mypy to use query-based architecture #12911 - GitHub
I think mypy would benefit from refactoring to use a query-based architecture similar to the one used by Rust's compiler or rust-analyzer ...
Read more >
Code Refactoring Best Practices: When (and When Not) to Do It
This method involves creating new classes and moving functionality between old and new classes. When one class has too much going on, it's...
Read more >
The Complete Engineer's Guide to Code Refactoring - Stepsize
Refactoring is a process of improving your codebase without creating new functionality. It helps you clean up your code and simplify design.
Read more >
Refactoring using type constraints - University of Washington
Most of the programs used in the experiments discussed in Section 6 use reflec- tion, but we have checked that the type constraints...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found