#Generics to the rescue for Radio Options?

12 messages · Page 1 of 1 (latest)

analog rampart
#

I'm looking for a way to quickly define the available values/options for a radio group But I can't figure out a way to make it works without some compromises.
My naive approach (but won't work) would ideally be this:

import React from 'react'

type FieldValues = Record<string, unknown>

type Form = {
  choices: 'foo' | 'bar' | 'baz'
}

type Radio<T extends {[K in keyof T]: T[K]}> = {
  name: K
  options?: {label: string, value: T[K]}
}

function Radio<T extends FieldValues>({name, ...props}: Radio<T>) {
  return null
}

function App() {
  return (
    <>
      <Radio<Form> name='choices' />
    </>
  )
}

You define once and for all your form, and you use your name in order to derive the values. But obviously typescript doesn't know what is K here...
My second approach would be this:
https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wChSYBPMJOAMWCQBsATANRSYFckBnOALyIkaaCwA8vGFGAA7AOYAaOF1kBrWRADusgHzkqNetDxCA3qThw0ACwjA0fAFwFMECPjgAfAgCMUUJ4++P4AXmQAvgbUtAgoLMAQ4gAqcEgAHjBIsiz8DMzsnDy8ygDSaZnZuXBqSJQQmHDJuoJwFlayKCBILqWWcBBgMImyvAD8LmZMKL7MLlIyCsoAbkU9TQDapQC6UVGkmKoYI4jxiSkVWTl5jKwc3Hxll1X8tfWNzQAUZp3dygB0gLAODAvAiLjiCSSyTKugAlG1+kQYFwoLI4LIuEwmKR9odZMcIOiAIJgMCfBHtODI1Hoz79KzifRWFlwcSQ850EzKfC2eyOXj4Fq-JACXl2Bx8TwAemZLPEsv6cNxQA
But I kind have to repeat myself, so I really don't like it, furthermore, I don't even have autocomplete on the generic part.

I think I'm making this too complicated compared to what it should be but I can't figure out a way to handle this. What am I missing here?

magic cedarBOT
#

@analog rampart Here's a shortened URL of your playground link! You can remove the full link from your message.

Ekaradon#3441

Preview:```ts
import React from "react"

type FieldValues = Record<string, unknown>

type Form = {
choices: "foo" | "bar" | "baz"
}

type Radio<T extends {[K in keyof T]: T[K]}> = {
name: K
options?: {label: string; value: T[K]}
}

function Radio<T extends FieldValues>({
name,
...props
}: Radio<T>) {
...```

rustic echo
#

@analog rampart You need to slightly change your radio generic for that to work

#
type Radio<T extends FieldValues, K extends keyof T = keyof T> = {
  name: K
  options?: { label: string, value: T[K] }
}
magic cedarBOT
#
ChronicStone#1283

Preview:```ts
import React from "react"

type FieldValues = Record<string, unknown>

type Form = {
choices: "foo" | "bar" | "baz"
}

type Radio<
T extends FieldValues,
K extends keyof T = keyof T

= {
name: K
options?: {label: string; value: T[K]}
}

function Radio<T extends FieldValues>({
name,
...props
}: Radio<T>) {
...```

analog rampart
#

Oh sweet! Like I wanted!

rustic echo
#

You can see that K (the key) does not need to be instanciated when you use Radio<..>, it's auto-assigned, BUT it also needs to explicitely state that it extends the keys of T, otherwise TS will yell at you & you won't get the value in options property correctly inferred

analog rampart
#

I see that. But I don't understand why we need to set the default 😮

#

Oh yeah in order to declare it

#

Okay!

#

Got it! Thanks a lot ChronicStone! ❤️

#

!close