How can treat string as string literal when mapping object in typescript

464 Views Asked by At

Here is my code

I tried my best to narrow down the type, the Name is still string

    type Item = { readonly name: string }
    const foo: Item = { name: 'foo' } as const
    const bar: Item = { name: 'bar' } as const
    const arr: readonly Item[] = [foo, bar] as const
    const names = arr.map(x => x.name)
    type Name = typeof names[number]  //string

When I remove the type declaration, I got the desired result. I do not know why this work, just tried it out randomly. Actually, the declaration is necessary and it is unacceptable to remove declaration.

    const foo = { name: 'foo' } as const
    const bar = { name: 'bar' } as const
    const arr = [foo, bar] as const
    const names = arr.map(x => x.name)
    type Name = typeof names[number] // "foo"|"bar"

type Item<T> = { name: T }
const foo: Item<'foo'> = getItem({ name: 'foo' })
const bar: Item<'bar'> = getItem({ name: 'bar' })
const arr = [foo, bar] as const
const names = arr.map(x => x.name)
type Name = typeof names[number]

The above can also work, but it looks redundant and stupid

type Item<T extends string> = { name: T }
const getItem = <T extends string>(args: Item<T>): Item<T> => {
  return args
}
const foo = getItem({ name: 'foo' })
const bar = getItem({ name: 'bar' })
const arr = [foo, bar] as const
const names = arr.map(x => x.name)
type Name = typeof names[number]

Here is the "best" solution I can came up with. Still I can not explain how it work just test it out blindly. And the getItem is pointless at all from a javascript perspective, not sure if this is a common practice

So can anyone explain how everything work, and is there any better solution to get the job done?

0

There are 0 best solutions below