Typescript generics: infer type from second parameter to use in the first

Viewed 194

I have such code:

export type Subscribe<T extends object> = <U>(
  listener: (slice: U) => void,
  selector: (state: T) => U,
) => void

// implementation doesn't matter
const subscribe = {} as Subscribe<{ value: number }>

subscribe(
  (value) => value * 2, // ts error: object is of type unknown
  (state) => state.value
)

Seems that it's impossible to do with typescript to infer type in this way

But if I change the order of parameters it works fine:

export type Subscribe<T extends object> = <U>(
  selector: (state: T) => U,
  listener: (slice: U) => void,
) => void

const subscribe = {} as Subscribe<{ value: number }>

subscribe(
  (state) => state.value,
  (value) => value * 2 // now no error! number type is inferred
)

I wish selector to be second parameter to make it optional, please let me know whether it's impossible or if you know the way

1 Answers

Consider this exmaple:

const subscribe = <
    T extends Record<PropertyKey, unknown>,
    ReturnValue,
    >(
        listener: (slice: ReturnValue) => void,
        selector: (state: T) => ReturnValue,
) => {}

subscribe(
    (value) => value * 2,
    (state: { value: number }) => state.value
)

Playgroud

I'm not sure you need a separate type for it. You can infer all generics from a function level

Related