Spread types may only be created from object types in TS

avatar

Borislav Hadzhiev

Last updated: Mar 9, 2022

banner

Photo from Unsplash

Spread types may only be created from object types in TS #

The "Spread types may only be created from object types" error occurs when we try to use the spread operator with a value that is possibly not an object. To solve the error, use a conditional to make sure the value is an object before using the spread operator.

Here are 2 examples of how the error occurs.

index.ts
type Person = { name: string } | undefined; const val1: Person = undefined; // ⛔️ Error: Spread types may only be // created from object types.ts(2698) console.log({ ...val1 }); const val2 = false; // ⛔️ Error: Spread types may only be // created from object types.ts(2698) console.log({ ...(val2 && { name: 'James' }) });

In the first example, the val1 variable can either store an object or an undefined value.

Trying to use the spread syntax with an undefined value causes the error.

In the second example, the expression evaluates to false, so we try to use the spread syntax with a boolean value and get the error.

The spread syntax (...) can only be used with object types.

To solve the error, we have to make sure the value we are using the spread syntax with is an object.

If you are absolutely positive the value is an object and TypeScript is getting confused, use a type assertion.

index.ts
const obj1 = Math.random() > 0.5 ? { name: 'James' } : true; const result = { ...(obj1 as Record<string, unknown>) };

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

We effectively tell TypeScript that obj1 will be an object and not to worry about it.

This approach shouldn't be used unless you're absolutely sure the value is of the expected type.

Another approach to solving the error is to use a type guard.

index.ts
type Person = { name: string } | undefined; const val1: Person = Math.random() > 0.5 ? undefined : { name: 'James' }; const result = { ...(typeof val1 === 'object' ? val1 : {}) }; console.log(result.name?.toUpperCase());

The val1 variable can either have a value of undefined or be an object.

We used a ternary operator with the spread syntax to provide an empty object as a fallback in case the val1 variable does not store an object.

This makes TypeScript happy, because there is no chance we try to use the spread syntax with an undefined value.

If you don't like this approach, try using the Object.assign() method, which is more forgiving.

index.ts
const result = Object.assign({}, false, true, undefined, null, 0, { name: 'James', }) as { name: string }; console.log(result.name); // 👉️ "James"

The parameters we passed to the Object.assign method are:

  1. the target object - the object to which the provided properties will be applied
  2. the source object(s) - one or more objects that contain the properties we want to apply to the target object
It's important that the first parameter you pass to the method is an empty object because that's where the properties of the source objects will be merged.

However, we are able to pass pretty much any value to the Object.assign method without TypeScript yelling at us.

Notice that we used a type assertion to type the result variable. Had we not done this, it would have been typed as any.

Conclusion #

The "Spread types may only be created from object types" error occurs when we try to use the spread operator with a value that is possibly not an object. To solve the error, use a conditional to make sure the value is an object before using the spread operator.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.