DEV Community

Cover image for A week of JavaScript tips, collected
JSLab
JSLab

Posted on

A week of JavaScript tips, collected

Seven tips, one for each day of the week. Each one replaces a helper you used to write, a library you used to install, or a bug you used to ship. All of them work in current Node, Bun and evergreen browsers.

Monday: .at(-1)

const steps = ["parse", "check", "emit"];
steps.at(-1);  // "emit"
steps.at(-2);  // "check"
Enter fullscreen mode Exit fullscreen mode

No more arr[arr.length - 1]. Works on strings too.

Tuesday: toSorted doesn't mutate

const nums = [10, 1, 2];
const sorted = nums.toSorted((a, b) => a - b); // [1, 2, 10]
nums;                                          // still [10, 1, 2]
Enter fullscreen mode Exit fullscreen mode

sort sorts in place and returns the same array, which surprises everyone once. toSorted, toReversed and toSpliced return a copy. And always pass a compare function: [1, 2, 10].sort() is [1, 10, 2], because the default sort compares strings.

Wednesday: structuredClone for deep copies

const original = { when: new Date(), tags: new Set(["a"]), nested: { n: 1 } };
const copy = structuredClone(original);
copy.nested.n = 2;
original.nested.n;           // 1
copy.when instanceof Date;   // true
Enter fullscreen mode Exit fullscreen mode

Unlike JSON.parse(JSON.stringify(x)), it keeps Dates, Maps and Sets. It throws on functions, which is a feature: you find out.

Thursday: Object.groupBy

const people = [{ name: "Ada", team: "core" }, { name: "Alan", team: "web" }, { name: "Grace", team: "core" }];
Object.groupBy(people, (p) => p.team);
// { core: [Ada, Grace], web: [Alan] }
Enter fullscreen mode Exit fullscreen mode

The reduce you've written a hundred times, built in. (More in #9.)

Friday: AbortSignal.timeout

await fetch("https://api.github.com/zen", { signal: AbortSignal.timeout(3000) });
Enter fullscreen mode Exit fullscreen mode

fetch has no timeout of its own. This one line gives it one, and rejects with a TimeoutError. (More in #10.)

Saturday: Error with cause

try {
  JSON.parse("{oops");
} catch (err) {
  throw new Error("Could not read settings", { cause: err });
}
Enter fullscreen mode Exit fullscreen mode

Your message says what you were doing, and err.cause still has the original error. (More in #7.)

Sunday: satisfies

const routes = {
  home: "/",
  docs: "/docs",
} satisfies Record<string, `/${string}`>;

routes.docs;      // fine, and autocomplete knows the keys
// routes.blog;   // error: Property 'blog' does not exist
Enter fullscreen mode Exit fullscreen mode

It checks that every value starts with /, without widening the object to Record<string, …>, so you keep the exact keys. (More in #6.)

Trying them

Each of these is a two-line experiment, which is what a scratchpad is for. In JSLab, a JavaScript & TypeScript scratchpad for macOS, Auto Log puts the value of each top-level expression beside its line as you type. In Tuesday's block, nums; shows up as ▸ Array(3); expand it to check it's still 10, 1, 2.

If a result surprises you, right-click it and choose Explain Result to ask Ask AI why. It works with your own key, or Ollama locally.

And if you'd like the tips about JSLab itself: in your first week, it shows a short tip in the status bar the first time you meet a feature, and Help → Learning & Tips has every feature with a video.

JSLab launches Nov 15. Learning & Tips: https://js-lab.app/docs/learn

Top comments (0)