#get correct type inference in switch statement

1 messages · Page 1 of 1 (latest)

red void
#

Given the following code:

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three',
}

type Value<T extends Option> = T extends Option.ONE
    ? string
    : T extends Option.TWO
    ? number
    : T extends Option.THREE
  ? boolean
  : never

export const parseCellValue = async <T extends Option, 
>(args: {
    cellType: T
    value: Value<T>
}) => {
    if (args.value === null) return args.value

    switch (args.cellType) {
        case Option.ONE: 
                return (args.value).toString()
        case Option.TWO: 
      // Property 'toFixed' does not exist on type 'string | number | boolean'.
      //  Property 'toFixed' does not exist on type 'string'.(2339)
            return args.value.toFixed(2) 
        case Option.THREE:
            return args.value
        default:
            throw new Error('Hmm')
    }
}

TS errors because it infers the type of args.value to be string | number | boolean

I expect args.value to get a stricter type inference (case Option.ONE should only be string)

I tried an if statement and it's the same issue

bleak duneBOT
#
carsoli#0

Preview:```ts
enum Option {
ONE = "one",
TWO = "two",
THREE = "three",
}

type Value<T extends Option> = T extends Option.ONE
? string
: T extends Option.TWO
? number
: T extends Option.THREE
? boolean
: never

export const parseCellValue = async <
T extends Option

(args: {
cellTy
...```

rancid silo
#

you should probably just have a manually constructed discriminated union instead of that conditional

#

the issue you have there is that, if T is a union, then cellType and value may not be from the same branch of the union

bleak duneBOT
#
that_guy977#0

Preview:ts ... type Cell = | { cellType: Option.ONE value: string } | { cellType: Option.TWO value: number } | { cellType: Option.THREE value: boolean } ...