Skip to content

One language feature I love in Swift, and in Objective-C before it, is how its function signatures include the name of the function and its arguments. In Swift, the functions Image(named: ‘my.image’) and  Image(systemName: "multiply.circle.fill") are not the same function Image() because their arguments differ.

As much as I adore it, this language feature is not available natively in modern javascript. You can mimic named arguments by passing an object to a constructor, but you’re still calling the same function each time. As a way to inject some Swift-ness into my javascript APIs, I have recently turned to a technique I call Static Initializers.

Static Initializers are static functions that return a new instance of the same type as their constructor. The returned instances are uniquely constructed with the function’s given arguments. There is no magic involved; it’s just a simple pattern. Here’s what it looks like when we recreate something like Swift’s Image initializers in javascript:

function UIImage() {
     …
 }
     
 UIImage.named(name) {
     const image = new UIImage()
     image.src = getImageSrc(name)
     return image
 }
     
 UIImage.systemName(name) {
     const image = new UIImage()
     name = name.toLowerCase()
     image.src = getSystemImageSrc(name)
     return image
 }

Our two UIImage initializers are very similar; the key difference is in how UIImage.systemName() conducts an additional safety measure, casting the name argument to lowercase before retrieving it from getSystemImageSrc().

The bodies of Static Initializers typically follow the same simple pattern:

  1. First, create the object using the main constructor.
  2. Then, configure the object using the given arguments, if applicable.
  3. Finally, return the configured object.

Here is what using Static Initializers looks like at the call site:

// Named
const myImage = UIImage.named(‘my.image’)

// System name
const commandIcon = UIImage.systemName(‘multiply.circle.fill’) 

Other than some minor differences in syntax, our javascript now reads very much like Swift, and no longer must we bother with dumping cumbersome configuration objects into each assignment. And. Even if our existing or legacy codebase has constructors that take configuration objects, nothing prevents us from tacking on new Static Initializers which build and pass that object along to the constructor on our behalf, reaping all the benefits of a clear and concise call site.

Cultivate

Join the Culture Foundry Community

Even if you’re not ready to make the leap yet, you’ll find our community to be a helpful source of key insights and advice to help you learn more about how to thrive in digital. All are welcome.

Join the Community