hand sketched logo of electrons orbiting a nucleus

TIL: Type Object and Keep String Literals

Just show me the code

const Foo = ({ name }: { name: string }) => <h1>{name}</h1>;

const Bar = ({ name }: { name: string }) => <span>{name}</span>;

// first try
const componentMap1: Record<string, (props: { name: string }) => JSX.Element> =
  {
    foo: (props) => <Foo {...props} />,
    bar: (props) => <Bar {...props} />,
  };

type ComponentName1 = keyof typeof componentMap1; // string  <--- we want 'foo' | 'bar'

// correct
const componentMap2 = {
  foo: (props) => <Foo {...props} />,
  bar: (props) => <Bar {...props} />,
} satisfies Record<string, (props: { name: string }) => JSX.Element>;

type ComponentName2 = keyof typeof componentMap2; // 'foo' | 'bar' <--- YAY!

More about satisfies from the release notes of TypeScript 4.9