Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid passing undefined for optional parameters

If I have a constructor that has n optional parameters and I want to pass a value for only the last optional parameter, I have to pass undefined n-1 times.

For example:

class House() {
    constructor(door?, roof?, windows?) { }
}

If I want to instantiate a new House that doesn't have a door or a roof but does have windows, I have to pass undefined twice to the constructor:

let myHouse = new House(undefined, undefined, new Windows());

C# has named parameters, which would be ideal here.

How can I avoid passing undefined n-1 times in this scenario?

like image 608
Dave Clark Avatar asked Jul 31 '17 12:07

Dave Clark


1 Answers

The most commonly used approach to this are parameter objects. Instead of using three parameters, you'd use one parameter:

interface HouseOptions {
    door?: Door;
    roof?: Roof;
    windows?: Windows;
}

class House() {
    constructor(options: HouseOptions) {...}
}

Now you can create a house like this: new House({windows: new Windows()})

This is even more flexible than named parameters: Consider the case where you want to allow Houses that have Windows and a Door OR have Windows and a Roof, but not houses that only have a roof. For this scenario, you can do something like this:

interface DoorlessHouseOptions {
    roof: Roof;
    windows: Windows;
}

interface RooflessHouseOptions {
    door: Door;
    windows: Windows;
}

class House() {
    constructor(options: DoorlessHouseOptions | RooflessHouseOptions) {...}
}

This enforces, that your house either has a door or a roof (along with Windows), in a type safe way, which would be complicated with named parameters. In some languages this could be solved by method overloading, but since Javascript does not allow method overloading, options-objects are usually the way to go.

Another, less commonly used approach would be the Builder pattern.

like image 152
Daniel Klischies Avatar answered Sep 28 '22 09:09

Daniel Klischies