Returning Objects from JS Arrow Functions Guide
Arrow functions need parentheses around the curly braces to return an object literal. Learn why () => ({ key: value }) works and () => { key: value } does not.
Arrow functions have a convenient implicit return: when the body is a single expression, you can drop the return keyword and the curly braces entirely, letting the expression's value become the return value automatically.
const add = (a, b) => a + b; // Implicitly returns a + bBut this convenience creates a problem when you want to return an object literal. An object literal also uses curly braces, and JavaScript cannot tell whether you mean a function body or an object.
The Problem
Writing an arrow function that tries to shortcut straight to an object literal looks reasonable, but it silently fails. This version does not work the way it appears to:
const createUser = (name) => {
name: name,
age: 30,
};
console.log(createUser("Alex")); // undefinedThe function returns undefined. Why? JavaScript sees the opening curly brace after the arrow and assumes it is a function block body.
Inside that block, name: is parsed as a JavaScript label, similar to a break target, not an object key. There is no return statement, so the function returns undefined.
The Solution: Wrap in Parentheses
Add parentheses around the object literal:
const createUser = (name) => ({
name: name,
age: 30,
});
console.log(createUser("Alex")); // { name: "Alex", age: 30 }The parentheses tell the parser: "this is an expression, not a block body." The curly braces inside the parentheses are unambiguously an object literal.
The Rule
When the token after the arrow is an opening curly brace, JavaScript assumes a block body. To return an object literal, wrap it in parentheses:
// Block body (needs explicit return)
const fn1 = () => {
return { key: "value" };
};
// Expression body returning an object (wrap in parentheses)
const fn2 = () => ({ key: "value" });Both work. The second is shorter. Choose whichever is clearer in context.
Common Patterns
The parenthesized-object pattern shows up constantly in real code, most often wherever a short callback needs to build a new object from its input.
In Array Methods
Transforming an array of objects into a new shape is one of the most common places this pattern appears:
const users = [
{ first: "Alex", last: "Chen" },
{ first: "Sara", last: "Khan" },
];
const names = users.map(user => ({
full: `${user.first} ${user.last}`,
initials: `${user.first[0]}${user.last[0]}`,
}));Each call to the callback builds and returns one new object, so map collects them into a new array of results:
console.log(names);
// [
// { full: "Alex Chen", initials: "AC" },
// { full: "Sara Khan", initials: "SK" },
// ]Without the parentheses, map would return an array of undefined values instead of the objects shown above.
In React Components
The same pattern appears whenever a list of items needs to become a list of props objects, such as before rendering each one as a component:
const items = ["a", "b", "c"];
const components = items.map((item, index) => ({
id: index,
label: item,
}));With Computed Property Keys
The rule applies the same way even when a property name is computed at runtime instead of written literally:
const prop = "score";
const createStats = (value) => ({
[prop]: value,
timestamp: Date.now(),
});
console.log(createStats(95)); // { score: 95, timestamp: 1747200000000 }With Spread Operator
Merging default values with overrides is another common case, and it needs the same parentheses since the result is still an object literal:
const defaults = { theme: "light", fontSize: 14 };
const withOverrides = (overrides) => ({
...defaults,
...overrides,
});
console.log(withOverrides({ theme: "dark" }));
// { theme: "dark", fontSize: 14 }When You Do NOT Need Parentheses
If the arrow function has a block body with an explicit return statement, no parentheses are needed around the object:
const createUser = (name) => {
const id = crypto.randomUUID();
return {
name,
id,
createdAt: new Date(),
};
};The return keyword makes the intent explicit, so there is no ambiguity. Use this form when you need to compute intermediate values before building the object.
Comparison
| Syntax | What it does |
|---|---|
() => { name: "Alex" } | Block body with a label. Returns undefined. |
() => ({ name: "Alex" }) | Expression body. Returns { name: "Alex" }. |
() => { return { name: "Alex" }; } | Block body with explicit return. Returns { name: "Alex" }. |
Why Only Arrow Functions?
Regular functions do not have this problem because the function keyword always precedes the body:
// No ambiguity: function keyword already established the context
const createUser = function(name) {
return { name, age: 30 };
};The ambiguity is unique to arrow functions because the arrow can be followed by either a single expression or a block body. For more on arrow function syntax, see JavaScript Arrow Functions: A Complete ES6 Guide. For when not to use arrows, see When to Avoid Using Arrow Functions in JavaScript.
Rune AI
Key Insights
- Wrap object literals in parentheses to return them from arrow functions: () => ({ key: value }).
- Without the parentheses, the braces are parsed as a block body, not an object literal.
- This only applies to arrow functions with expression bodies. Regular functions do not have this ambiguity.
- The pattern is common in map, filter chains, and React components.
- If the object has computed keys or spread properties, the same rule applies: wrap in parentheses.
Frequently Asked Questions
Why does () => { name: 'Alex' } return undefined?
Does this only apply to arrow functions?
Can I use this pattern in array methods like map?
Conclusion
Returning an object from an arrow function requires one small trick: wrap the curly braces in parentheses. () => ({ key: value }). Forget the parentheses and JavaScript sees a block body with a label, not an object literal. This is one of the most common arrow function mistakes, and now you know exactly why it happens and how to avoid it.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.