#enforce keys of object as items of array

20 messages · Page 1 of 1 (latest)

hasty notch
#

this is an object which keys i want to be used as items of an array

export const backgrounds = {
  none: {
    component: () => null,
  },
  bamboo: {
    component: () => Bamboo,
  },
} as const satisfies Record<string, { component: () => ReactNode }>

like so

const arr: MagicType = ['none', 'bamboo'] 

array includes the exact number of keys and they cannot repeat and be missing, meaning the array will scream red when a new property was added to backgrounds signaling that it needs to be filled

#

it looks like a good use for Pick or Infer but i am not very sure

sullen kindle
#

you can't really (practically + safely) do this, it would be easier to go the other way

hasty notch
#

hm, ok, but what way then?

#

i still desire coherence

still pineBOT
#
that_guy977#0

Preview:```ts
type ReactNode = unknown;
const Bamboo = {}

const arr = ['none', 'bamboo'] as const satisfies string[]

type ComponentType = typeof arr[number];

const backgrounds1 = {
none: {
component: () => null,
},
bamboo: {
component: () => Bamboo,
},
...```

hasty notch
#

alright

#

i did it in the past, i will do it again then

#

is there any other way btw?

#

curious

#

i know the above works nicely

sullen kindle
#

!:unsafe-keys

still pineBOT
#
retsam19#0
`!retsam19:unsafe-keys`:

Since TS allows objects to have extra properties not specified in the type, it doesn't assume that all the keys on the type are the only keys on the object. This means that Object.keys returns string[] not a specific type, and for(const key in obj), key is string, (not keyof typeof obj).

If you wish to assume otherwise, this utility is often helpful:

// A signature for `Object.keys` that assumes the only keys are the ones indicated by the type
const unsafeKeys = Object.keys as <T>(obj: T) => Array<keyof T>;
sullen kindle
#

!:u2t

still pineBOT
#
joshcena63#0
type U2I<U> = (
  U extends U ? (arg: U) => 0 : never
) extends (arg: infer I) => 0
  ? I
  : never

// For homogeneous unions, it picks the last member
type OneOf<U> = U2I<
  U extends U ? (x: U) => 0 : never
> extends (x: infer L) => 0
  ? L
  : never

type U2T<U, L = OneOf<U>> = [U] extends [never]
  ? []
  : [...U2T<Exclude<U, L>>, L]```
hasty notch
#

@sullen kindle thanks

#

!resolved

hasty notch