Repository: TypeScript
Issue: Refactor: Generate narrower type based on usage.
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

1. refactor 
2. type
3. narrow
4. generate
5. interface
6. decouple

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
My suggestion meets these guidelines:

* [X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [X] This wouldn't change the runtime behavior of existing JavaScript code
* [X] This could be implemented without emitting different JS based on the types of the expressions
* [X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [X] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

A new refactor feature which creates a minimal interface based on usage for an argument.

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->

Imagine we have created an interface, User. 

```ts
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.

```ts
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.
```ts

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: 
```ts
const renderTable = (data: (User|Book)[])=> {
// ...
```
Then, we add Libraries, and repeat

```ts
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.

```ts
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?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->
> 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.