Fuzzyma
Fuzzyma

Reputation: 8484

Narrow down type of callback Parameter

I have a function:

type Callback = (data: Record<string, unknown>) => void
const execCb = (cb: Callback) => {
  cb(somedata)
}

As you can see, data is pretty generic because it could be any object. However, when I define my callbacks, I would like to narrow down the data to specific types:

type MyCallBackData = {
  foo: string,
  bar: number
}
const myCallback = (data: MyCallBackData) => {
  // do something
}

execCb(myCallback)

Typescript complains, that Type 'Record<string, unknown>' is missing the following properties from type 'MyCallBackData': foo, bar

How can I properly narrow down a type in this case?

Plaground: Link

Upvotes: 0

Views: 207

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250036

The parameter Record<string, unknown>, means you can pass in a object with no properties (like you do, where you pass {}) but the callback you pass in requires proeprties on the first argument. So this is not type safe.

What you could do is make execCb generic, so the parameter can be any type. THis also means you won't be able to pass in a concrete object in execCb (at least not without a type assertion). You can for example pass it as an extra parameter to execCb.

type Callback<T> = (data: T) => void

const execCb = <T extends Record<string, unknown>>(cb: Callback<T>, param: T) => {
  cb(param)
}

type MyCallBackData = {
  foo: string,
  bar: number
}

const myCallback = (data: MyCallBackData) => {
  // do something
}

execCb(myCallback, {
  foo: "",
  bar: 1
})

Playground Link

Upvotes: 1

Related Questions