TypeScript Default Parameters and Destructuring As a Substitute for Named Parameters

–VIDEO TRANSCRIPT–

In this video I’ll demonstrate how to set default values for function parameters.

Some programming languages let you define a function with default parameter values like this:

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AddToCart</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> productName, <span class="hljs-keyword">decimal</span> price, <span class="hljs-keyword">int</span> quantity = <span class="hljs-number">1</span>, <span class="hljs-keyword">string</span> currency = <span class="hljs-string">"USD"</span></span>) </span>{
<span class="hljs-comment">// logic here</span>
}

In fact, with ES2015 we can now do very much the same thing.

A nice feature in other languages that is not available in JavaScript is calling a function with named parameters.

Named parameters let us quickly override default parameter values.

To call this function and override the currency value but accept the default values for all other parameters preceding it would look something like this:

AddToCart(<span class="hljs-string">"Bicycle"</span>, <span class="hljs-number">100.00</span>, currency: <span class="hljs-string">"CAD"</span>);

I call AddToCart with a product name and a price. Then I supply the function a currency parameter with the value of ‘CAD’ for Canadian Dollars.

The value of the quantity parameter will be 1 as that is the default value in the function’s signature.

In JavaScript, specifically ES2015, we now have access to default parameters. In addition, we also have destructuring which provides a way to extract the values we need.

What I’m going to show you won’t work in ES5 so you’ll need a transpiler like Babel or TypeScript.

I’ll be using TypeScript here but you can find the ES2015 solution in the notes below.

First let’s look at how to use default parameters.

I’ll create a addToCart function.

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToCart</span>(<span class="hljs-params">product: string, price: number, quantity = <span class="hljs-number">1</span>, currency = <span class="hljs-string">'USD'</span></span>) </span>{
...
}

And I’ll console log all of the parameters so I can see it in action.

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToCart</span>(<span class="hljs-params">product: string, price: number, quantity = <span class="hljs-number">1</span>, currency = <span class="hljs-string">'USD'</span></span>) </span>{
  <span class="hljs-built_in">console</span>.log(product, price, quantity, currency);
}

This is very similar to the C# example I showed earlier. The main differences are in the type annotations which you can ignore if you aren’t using TypeScript.

Now I’ll call the function and take the default parameters just to know everything is working.

addToCart(<span class="hljs-string">'Bicycle'</span>, <span class="hljs-number">99.99</span>);

Perfect! The console log shows the values I expected.

Now I’ll call it again, but this time I’ll change the currency to Canadian Dollars.

addToCart(<span class="hljs-string">'Bicycle'</span>, <span class="hljs-number">99.99</span>, currency = <span class="hljs-string">'CAD'</span>);

It looks like the TypeScript language service isn’t happy with my function call.

If I put my mouse over the code I can see what the issue is.

It’s trying to interpret our currency as the quantity parameter.

JavaScript, as well as TypeScript, doesn’t support this kind of assignment in a function call.

Instead I’ll need to provide a value for all the parameters preceding currency.

addToCart(<span class="hljs-string">'Bicycle'</span>, <span class="hljs-number">99.99</span>, <span class="hljs-literal">undefined</span>, <span class="hljs-string">'CAD'</span>);

When I pass a parameter an undefined value JavaScript will use the default value for that parameter.

This can be confusing when looking at the code later on.

To work around this limitation of JavaScript we can use destructuring to handle our default values and the power of TypeScript to manage our required parameters.

First I’ll start by creating an interface for our function parameters.

My interface will define the parameter names and their types.

I can’t include default values here since the interface will be discarded in the transpiled JavaScript.

interface AddToCartParameters {
  <span class="hljs-attr">product</span>: string;
  price: number;
  quantity?: number;
  currency?: string;
}

I’ll use the question mark to indicate the optional parameters. These are the parameters that will have default values in the function’s signature.

Then I’ll update my function parameters.

With destructuring I can set a default parameter with our AddToCartParameters interface.

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToCart</span>(<span class="hljs-params">{ product, price, quantity, currency }: AddToCartParameters</span>) </span>{
  <span class="hljs-built_in">console</span>.log(product, price, quantity, currency);
}

And I’ll call it like this:

addToCart({ <span class="hljs-attr">product</span>: <span class="hljs-string">'Bicycle'</span>, <span class="hljs-attr">price</span>: <span class="hljs-number">99.99</span> });

The console log shows the output with quantity and currency being undefined. That’s to be expected since I didn’t provide default values in the function definition.

I’ll add them now.

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToCart</span>(<span class="hljs-params">{ product, price, quantity = <span class="hljs-number">1</span>, currency = <span class="hljs-string">'USD'</span> }: AddToCartParameters</span>) </span>{
  <span class="hljs-built_in">console</span>.log(product, price, quantity, currency);
}

Now the console log shows the default values for both quantity and currency.

Since this function takes an object I can compose the parameters object however I like.

I’ll create a parameters object for a series of products.

<span class="hljs-keyword">let</span> Bicycle = {
  <span class="hljs-attr">product</span>: <span class="hljs-string">'Bicycle'</span>,
  <span class="hljs-attr">price</span>: <span class="hljs-number">99.99</span>
}

<span class="hljs-keyword">let</span> Helmet = {
  <span class="hljs-attr">product</span>: <span class="hljs-string">'Helmet'</span>,
  <span class="hljs-attr">price</span>: <span class="hljs-number">33.33</span>
}

<span class="hljs-keyword">let</span> Bell = {
  <span class="hljs-attr">product</span>: <span class="hljs-string">'Bell'</span>,
  <span class="hljs-attr">price</span>: <span class="hljs-number">11.11</span>
}

Now I’ll add all of these products to the cart but I’ll change the currency to Canadian Dollars.

<span class="hljs-built_in">Array</span>(Bicycle, Helmet, Bell).forEach(<span class="hljs-function"><span class="hljs-params">product</span> =></span> {
  <span class="hljs-keyword">let</span> cartParams: AddToCartParameters = <span class="hljs-built_in">Object</span>.create(product);
  cartParams.currency = <span class="hljs-string">'CAD'</span>;
  addToCart(cartParams);
});

One thing that may cause you pain with this approach is the need to always provide a named parameter. It doesn’t need to be this way.

I’ll split up the function’s parameters making the required parameters separate from the default parameters.

Now that my object will only have default parameters I don’t need the rely on the interface anymore. Instead I’ll let TypeScript infer the types from the default values. This reduces the amount of code I need to maintain.

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addToCart</span>(<span class="hljs-params">product: string, price: number, { quantity = <span class="hljs-number">1</span>, currency = <span class="hljs-string">'USD'</span> }</span>) </span>{
  <span class="hljs-built_in">console</span>.log(product, price, quantity, currency);
}

And I’ll update the loop that adds the products to the cart.

<span class="hljs-built_in">Array</span>(Bicycle, Helmet, Bell).forEach(<span class="hljs-function"><span class="hljs-params">product</span> =></span> {
  addToCart(product.product, product.price, { <span class="hljs-attr">currency</span>: <span class="hljs-string">'CAD'</span> });
});

I’ll save it. The console is showing the correct information.

While JavaScript doesn’t have named parameters baked in, this approach gets us pretty close.

ES2015 Version

CSG Pro

CSG Pro

Our data analytics consultants solve problems and ignite victories. We help you understand your data so you can make smarter business decisions. We build custom software applications that strengthen your process and your team.
SHARE THIS
Share on twitter
Share on facebook
Share on linkedin
Share on email
RELATED POSTS
Stay Connected

Subscribe to CSG Pro. We’ll supply your inbox with the latest blog posts, training videos, and upcoming events.

Search

Ready to wrangle your data?