Typescript intellisense isn't working on mapped return type

Viewed 16

I'm trying to write an event bus function that will return a few fixed helper functions such as get, set and sub. However I want to optionally allow a user to register additional functions (I'm calling reducers) but my function instance only intellisenses get, set and sub.


type Tail<T extends any[]> = T extends [any, ...infer U] ? U : never

type EventBus<T> = {
  get: () => T
  set: (atom: T) => void
  sub: (cb: (atom: T) => any) => number
}

type Reducers<T> = Record<string, (atom?: T, ...args: any[]) => T>

type ReducerCallbacks<T extends Record<string, (...args: any[]) => void>> = {
  [P in keyof T]-?: (...args: Tail<Parameters<T[P]>>) => void
}

function PubSub<T>(
  atom: T,
  reducers?: Reducers<T>,
): EventBus<T> & ReducerCallbacks<typeof reducers> {
  let _atom = atom
  const _subscribers: ((atom: T) => any)[] = []
  const _get = (): T => _atom
  const _set = (atom: T) => ((_atom = atom), _subscribers.forEach(i => i(_atom)))
  const _sub = (cb: (atom: T) => any) => _subscribers.push(cb)

 // remove the first argument from all the reducer functions
  const _reducers: ReducerCallbacks<typeof reducers> = reducers
    ? Object.entries(reducers).reduce((acc, [k, v]) => {
        acc[k] = (...args:Tail<Parameters<typeof v>>[]) => _set(v(_atom, ...args))
        return acc
      }, {} as ReducerCallbacks<typeof reducers>)
    : null
  return { get: _get, set: _set, sub: _sub, ..._reducers }
}

const ps = PubSub<number>(0, {
  inc: atom => atom + 1,
  dec: atom => atom - 1,
  reset: () => 0,
  sum:(atom, d:number) => atom + d
})


// These aren't intellisensed
ps.reset()
ps.sum()

enter image description here

0 Answers
Related