Repository: TypeScript
Issue: Feature request: Track references of string literals on keys and vice-versa for better intellisense
Labels: Bug,Help Wanted,Effort: Moderate,Effort: Difficult,Domain: Refactorings

# Suggestion
## 🔍 Search Terms

rename string literals, refactor

## ✅ Viability Checklist
* [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

[Playground for code below](https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEYD2A7AzgF3gMwIwC54AeAFQD4AKKQkgGngCNCBveAbQGl4BLFeAaxABPJNngkAujU4T4AXwCU8ALxl4ANyTdgAKB14KzHfBxIkhCktXxmcnXPpGT2Mxatrb9hToD0PxBgwEADUkNxg-PCojADkaKZI9NxYKFDq3ADmUBgg8RhI8FBxCfAAtKXwKOEgAIS+-mCBIWERUXxF8S6JPFhoABZIAO7xDMVdhfFQ8HDYIHAoYAjlldV1ftMgqQC2vBltCOPzUFu58Bh9CEjncyX5BctVi3U6oJCwCMjoWNgATISklGo4noTAEwlE4ncGi0un0P0MxgSbhUHjsDngACIuhjvOtGkFQhBwpFoqNOmZ6MAkKcUFc+rsyhUwFA+AwENwtgAHGBIdQgYCMISVNKZbIM-KFMZmNYNJqE4ltSXk7pUml0hnLZms9lcnl8gUMIX9IYMsklKCTDazeZPeobbYM1AHMzwVVoFAxLBHE5nC5Ra4wW4uzUsxg67m8-nPV7QOCIVCYHAAZn+XBAAA8cihgPFMDBdoDCBwQSx2AB9Hh8DhSeAAVxQ-Fpgz4ihR0O0emwSYoWLMGMciK6yOsnkUdvxzSJrVJUpV1PitPOGqZobZPF1kYNQtS6SyGHFBQ6CRlAQJLRJ7VnlPnlXVKD2Ie164j+sF8GNg1Ns4mhStc02trrN6jooM6BRuh6XqbMcCDXP6FyBuMdyMogq7hnqUZAA)
```ts
declare const f1: <T>(a: T, b: { [K in keyof T]: T[K] }) => void

f1({
  foo: () => {}
}, {
  foo: () => {}
})
// ctrl+click on b's foo, it navigates to a's foo -- nice!
// ctrl+click on a's foo, it shows b's foo as a reference -- nice!
// renaming one foo renames the other foo too -- nice!

declare const f2: <T>(a: T, b: keyof T) => void

f2({
  foo: () => {}
}, "foo")
// ctrl+click on b's foo, does nothing -- can be improved by navigating to a's foo!
// ctrl+click on a's foo, does nothing -- can be improved by showing b's foo as a reference!
// renaming one foo doesn't rename the other foo too -- can be improved!

declare const f3: <K extends string>(a: K, b: { [_ in K]: unknown }) => void

f3("foo", {
  foo: () => {}
})
// ctrl+click on b's foo, does nothing -- can be improved by navigating to a's foo!
// ctrl+click on a's foo, does nothing -- can be improved by showing b's foo as a reference!
// renaming one foo doesn't rename the other foo too -- can be improved!
```

## 📃 Motivating Example

A bunch of popular libraries that will benefit from this for example...

### 1. [xstate](https://xstate.js.org)
```ts
// @file machine.ts
import { createMachine } from "xstate"

export const postMachine = createMachine({
  initial: "idle",
  states: {
    idle: { entry: "doStuff" }
  }
})

// @file index.tsx
import { useMachine } from "@xstate/react"
import { postMachine } from "./machine"

const Post = () => {
  let machine = useMachine(postMachine, {
    actions: {
      doStuff: () => {
      
      }
    }
  })
}
```
This feature will enable ctrl+click on "doStuff" in index.tsx navigating to "doStuff" in machine.ts and renaming both "doStuff" by renaming either of them (given the types are correct ofc)

### 2. [stitches](https://stitches.dev/)

Taken from [here](https://stitches.dev/docs/variants#adding-variants)
```ts
const Button = styled('button', {
  variants: {
    color: {
      violet: {
        backgroundColor: 'blueviolet',
        color: 'white',
        '&:hover': {
          backgroundColor: 'darkviolet',
        },
      },
      gray: {
        backgroundColor: 'gainsboro',
        '&:hover': {
          backgroundColor: 'lightgray',
        },
      },
    },
  },
});

() => <Button color="violet">Button</Button>;
```

Here the string literal `"violet"` in `<Button color="violet">Button</Button>` references the `violet` key in the object passed to `styled` function

### 3. [framer-motion](https://www.framer.com/motion/)

Taken from [here](https://www.framer.com/docs/examples/#variants)
```ts
import { motion } from "framer-motion"

const variants = {
  open: { opacity: 1, x: 0 },
  closed: { opacity: 0, x: "-100%" },
}

export const MyComponent = () => {
  const [isOpen, setIsOpen] = useState(false)

  return (
    <motion.nav
      animate={isOpen ? "open" : "closed"}
      variants={variants}
    >
      <Toggle onClick={() => setIsOpen(isOpen => !isOpen)} />
      <Items />
    </motion.nav>
  )
}
```
Here the string literals `"open"` and `"close"` in `motion.nav`'s `animate` reference the keys of `variants` passed to it.

These three come to my mind right now, but I think this is a very common pattern so the improvement in the intellisense will have a significant impact.