1

is it posible to change the type of something based on the value of an argument passed to a function. I need this kind of type for an event emiter with callback. Example:

interface IUser {
  name: string
}

type CallBack = /* the Type for the Callback that should be dynamic */

//for event1 the type CallBack should be (user: IUser) => any
use("event1", (user) => { /* check that event1 is used, so only add 1 argument to the callback type  */ })

//for event2 the type CallBack should be (email: string, password: string) => any
use("event2", (email, password) => { /* check that event12is used, so add 2 argument to the callback type */ })

so is there a way to detect which event is used and apply the right type to the callback?

1

2 Answers 2

3

The simplest way to do it is with overloads.


type CallBack = {
  (name: "event1", cb: (u: IUser) => void): void
  (name: "event2", cb: (email:string, pass: string) => void): void
}

let use: CallBack = null!;
//for event1 the type CallBack should be (user: IUser) => any
use("event1", (user) => { /* check that event1 is used, so only add 1 argument to the callback type  */ })

//for event2 the type CallBack should be (email: string, password: string) => any
use("event2", (email, password) => { /* check that event12is used, so add 2 argument to the callback type */ })

Playground Link

If you have a more complex scenario, such as already having the callbacks in another type, or more complicated conditions, you might consider tuples in rest parameters and conditional types. But from your question, that would be overkill.

Sign up to request clarification or add additional context in comments.

Comments

0

You could use types like this:

type CallBackEvent1 = (event: "event1", cb: (user: IUser) => void) => void;
type CallBackEvent2 = (
  event: "event2",
  cb: (email: string, pass: string) => void
) => void;

type CallBack = CallBackEvent1 | CallBackEvent2;

const callBack1: CallBack = (event: "event1", cb: (user: IUser) => void) =>
  undefined;
const callBack2: CallBack = (
  event: "event2",
  cb: (email: string, pass: string) => void
) => undefined;

const wrongCallBack: CallBack = (event: "event2", cb: (user: IUser) => void) =>
  undefined;
// Type '(event: "event2", cb: (user: IUser) => void) => undefined' is not assignable to type 'CallBack'.
//   Type '(event: "event2", cb: (user: IUser) => void) => undefined' is not assignable to type 'CallBackEvent1'.
//     Types of parameters 'event' and 'event' are incompatible.
//       Type '"event1"' is not assignable to type '"event2"'.ts(2322)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.