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