Skip to content

Way to handle optional fields in typescript? #13

@muradm

Description

@muradm

(duck typing)

type Data = {
  firstname: string
  lastname?: string
  settings?: {
    theme: 'dark' | 'light'
  }
}

function NamePart({ lens }: { lens: Lens<string> }) {
  return lens.interop((control, name) => (
    <Controller {...{ control, name }}  render={({ field }) => <TextField {...field} />}   />
  )
}

function OptionalNamePart({ lens }: { lens: Lens<string | undefined> }) {
  return lens.interop((control, name) => (
    <Controller
      {...{ control, name }}
      render={({ field: { value, onChange, ...field } }) => (
        <TextField {...field} value={value ?? ''} onChange=((e) => {
         const v = e.target.value
         onChange(isEmpty(v) ? undefined : v)
        }) />
      )}
    />
  )
}

function Fullname({ lens }: { lens: Lens<{ firstname: string, lastname?: string }> }) {
  return (
    <>
      {/* works */}
      <NamePart lens={lens.focus('firstname')} />
      {/* works */}
      <OptionalNamePart lens={lens.focus('lastname')} />
      {/* 1. type does not match */}
      <OptionalNamePart lens={lens.focus('firstname')} />
    </>
  )
}

function Settings({ lens }: { lens: Lens<NonNullabel<Data['settings']>> }) {
  return  <></> // ... omitted
}

function Form() {
   const { control } = useForm<Data>()
   const lens = useLens({ control })
   return (
     <>
       <Fullname lens={lens.reflect(l) => ({
         firstname: l.focus('firstname'),
         lastname: l.focus('lastname'),
       })} />
       {/*  2. This results in: `Lens<undefined> | Lens<NonNullable<Data['settings']>> ` which is unassignable/unassertable  */}
       <Settings lens={lens.focus('settings')} />
     </>
   )
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions