Home > Mobile >  How to make second method parameter required based on first parameter value
How to make second method parameter required based on first parameter value

Time:08-21

i am trying to create a class method in which the second parameter needs to be dynamically optional or required depended on first parameter value

This is my type containing interfaces:

type Settings = {
  AddPaymentInfo: AddPaymentInfo
  AddToCart: AddToCart
  AddToWishlist: AddToWishlist
  CompleteRegistration: CompleteRegistration
  Contact: Contact
  CustomizeProduct: CustomizeProduct
  Donate: Donate
  FindLocation: FindLocation
  InitiateCheckout: InitiateCheckout
  Lead: Lead
  Purchase: Purchase
  Schedule: Schedule
  Search: Search
  StartTrial: StartTrial
  SubmitApplication: SubmitApplication
  Subscribe: Subscribe
  ViewContent: ViewContent
}

this is my method in my class

  track<T extends keyof Settings>(
    pixelCmd: T,
    settings?: Settings[T]
  ): {
    if (typeof window !== 'undefined') {
      window.fbq('track', pixelCmd, settings)
    }
  }

With this approach i just solved one problem (make the second parameter to have a type based on first parameter. It is what i ALSO wanted, but now i want to make this second parameter to be required based on some specific properties, lets say for example "Purchase" should be a property that enforces second parameter to be REQUIRED

So if if tried to call this method like shown below, i'd like typescript warn me "expected 2 arguments":

const myClass = new MyClass()

myClass.track('Purchase')

And if i tried to call the method like shown below, considering the property "Lead" is a property that should make the second parameter OPTIONAL, typescript wouldn't complain:

const myClass = new MyClass()

myClass.track('Lead')

CodePudding user response:

You could use a variadic tuple type as the argument of the function and use a conditional to evaluate either to a tuple of length 1 or 2 based on the given key T.

type Settings = {
  AddPaymentInfo?: string
  AddToCart?: number
  Lead?: boolean
  Purchase: Date
}

function track<T extends keyof Settings>(
    ...args: undefined extends Settings[T] 
      ? [pixelCmd: T, settings?: Settings[T]] 
      : [pixelCmd: T, settings: Settings[T]]
) {}


track("Purchase") // Error: Source has 1 element(s) but target requires 2
track("Purchase", new Date())
track("Lead", 2) // Error: type number is not assignable to type boolean | undefined
track("Lead") // Ok
track("Lead", true) // Ok

Playground

  • Related