Skip to content

Feature request: Track references of string literals on keys and vice-versa for better intellisenseΒ #45549

Open
@devanshj

Description

@devanshj

Suggestion

πŸ” Search Terms

rename string literals, refactor

βœ… Viability Checklist

  • 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

Playground for code below

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

// @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

Taken from here

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

Taken from here

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: Refactoringse.g. extract to constant or function, rename symbolEffort: DifficultGood luck.Effort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".Help WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions