Assigning default properties efficiently with Defu
Tags: javascript, typescript, opensource, node
Published: 2023-12-04 09:06:55

Merging two object into one was always a challenge for me. While the use cases for it can be quite common like assigning default properties to a configuration object.

I never really had a go to solution for solving that problem until I found out about [Defu](https://github.com/unjs/defu) by UnJS organization. I discovered this tool while working on one of my Nuxt modules and it has proven to be extremely useful in many different cases.

But apart from the fact that it delivers a great value out of the box, you can also customise it  for more advanced cases where you may not want a default merging strategy in some cases. I will show you an example later on that I am using on a daily basis in my Nuxt Security module.

Enjoy!

## What is Defu?

Defu is a JavaScript package that allows you to assign default properties, recursively and it is really lightweight and fast.

So, basically what it does it allows you to efficiently merge two objects into one.

## Usage

In order to use Defu in your application, first install the package like following:

```
yarn add defu
```

And that's it! You can start using defu in your app like following:

```ts
import { defu } from "defu";

const options = defu(object, ...defaults);
```

The `options` object will have a structure of combined `object` and `...defaults`.

To give you more insights into how it will work, let's take a look at this real example:

```ts
import { defu } from "defu";

const defaults = { a: { b: 1, c: 3 } }
const options = { a: { b: 2 } }

const mergedOptions = defu(options, defaults)

console.log(mergedOptions);
// => { a: { b: 2, c: 3 } }
```

As you can see from the example above, the value of `mergedOptions` is `{ a: { b: 2, c: 3 } }` which means that Defu took the structure of `defaults` object and assigned properties from `options` object into it instead of replacing the existing `a` object property as it would be done normally. 

Quite useful if you ask me ;)

## More advanced use cases

Sometimes default merging strategy is not enough. Using `createDefu` it is possible to create a custom instance with different merging strategy.

`createDefu` function accepts obj (source object), key and value (current value) and should return true if applied custom merging.

Let's take a look at following example where we want to sum numbers instead of overriding the properties:

```ts
import { createDefu } from "defu";

const sumDefu = createDefu((obj, key, value) => {
  if (typeof obj[key] === "number" && typeof value === "number") {
    obj[key] += value;
    return true;
  }
});

sumDefu({ cost: 5 }, { cost: 10 }); // { cost: 15 }
```

You can see already how useful this package can be. And this is just the beginning! Take a look at the README.md for more examples https://github.com/unjs/defu 

## Bonus - usage of Defu in Nuxt Security

If you are have not yet seen [NuxtSecurity](https://github.com/baroshem/nuxt-security) I highly recommend you to try it out! It is a module that helps you make more secure Nuxt apps by default. It comes with useful features like Security response headers and middleware like Rate Limiter, CORS, CQRS, XSS, and many more!

In NuxtSecurity, I was using the default merging strategy of Defu but at certain point I realised that it does not work the way I wanted if there was an array passed as an object property (common case for Browser response headers where values as arrays).

So one of the community contributors Qrzy (Marcin Kurkiewicz) created a custom defu merger that would help with this array issue:

```ts
import { createDefu } from 'defu'

export const defuReplaceArray = createDefu((obj, key, value) => {
  if (Array.isArray(obj[key]) || Array.isArray(value)) {
    obj[key] = value
    return true
  }
})
```

And it is working really well until today!

## Courses & Certifications

If you are looking for great courses and certifications to practice Vue, Nuxt, JavaScript, and more, check out following links:

- https://vue.school/bundle-baroshem

## Summary

Nicely done! You have just learned how to use Defu to efficiently merge objects. Let me know what other advanced use cases you have in your apps :)

Take care and see you next time!