Modern JavaScript & TypeScript
Before writing code
Fetch live docs: Web-search site:developer.mozilla.org javascript for MDN JavaScript reference. Check https://www.typescriptlang.org/docs/ for TypeScript documentation.
ES6+ Features
Arrow Functions
Concise function syntax with lexical this:
const add = (a, b) => a + b;
- Implicit return for single expressions
- No own
this, arguments, super, or new.target
Template Literals
String interpolation and multi-line strings:
`Hello, ${name}!`
- Tagged templates for DSLs
Destructuring
Extract values from objects/arrays:
const { name, price } = product;
const [first, ...rest] = items;
- Default values:
const { name = 'Unknown' } = product;
- Nested:
const { address: { city } } = customer;
Spread / Rest
- Spread:
[...arr1, ...arr2], { ...obj1, ...obj2 }
- Rest:
function(...args) {}, const { a, ...rest } = obj;
Modules (ES Modules)
import { func } from './module.js';
export const value = 42; / export default class {}
- Dynamic:
const mod = await import('./lazy.js');
Optional Chaining & Nullish Coalescing
obj?.property?.nested — short-circuits to undefined if any part is nullish
value ?? defaultValue — returns right side only if left is null/undefined (not falsy)
Async Patterns
Promises
new Promise((resolve, reject) => { ... })
.then(), .catch(), .finally()
Promise.all(), Promise.allSettled(), Promise.race(), Promise.any()
Async/Await
async function fetchData() { const data = await fetch(url); }
- Error handling with try/catch
- Parallel:
const [a, b] = await Promise.all([fetchA(), fetchB()]);
Fetch API
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();
TypeScript
Type Annotations
let name: string = 'Product';
function getPrice(id: number): Promise<number> { ... }
const product: Product = { ... };
Interfaces
interface Product {
id: string;
title: string;
handle: string;
priceRange: {
minVariantPrice: { amount: string; currencyCode: string };
};
variants?: Variant[];
}
Type Utilities
Partial<T> — all properties optional
Required<T> — all properties required
Pick<T, K> — subset of properties
Omit<T, K> — exclude properties
Record<K, V> — key-value mapping
ReturnType<T> — extract return type of function
Generics
function fetchResource<T>(url: string): Promise<T> {
return fetch(url).then(res => res.json());
}
const product = await fetchResource<Product>('/api/products/1');
Enums
enum OrderStatus {
Pending = 'pending',
Shipped = 'shipped',
Completed = 'completed',
}
Discriminated Unions
type ApiResponse<T> =
| { status: 'success'; data: T }
| { status: 'error'; message: string };
Modern Array Methods
map, filter, reduce, find, findIndex
some, every — boolean checks
flat, flatMap — array flattening
Array.from(), Array.isArray()
Object.entries(), Object.fromEntries(), Object.keys(), Object.values()
structuredClone() — deep clone
For Shopify Specifically
Theme JavaScript
- Vanilla JS or minimal libraries — themes should stay lightweight
- Use
<script defer> and lazy loading for performance
- Access Liquid data via
<script type="application/json"> blocks
- No build step required — Shopify serves assets directly
Shopify Functions (Wasm)
- JavaScript compiled to WebAssembly
- No async (no Promises, no fetch) — synchronous only
- Pure functions: input → output, no side effects
- TypeScript recommended for type safety on I/O schemas
Hydrogen / Remix
- TypeScript by default
- React components with hooks
- Server Components + Client Components
- Remix loaders and actions (server-side)
- Type-safe Storefront API queries
App Development
- Remix server with TypeScript
- Polaris components for admin UI
- App Bridge for embedded app communication
@shopify/shopify-app-remix for auth and session management
Best Practices
- Use
const by default, let when reassignment is needed, never var
- Use async/await over raw Promises for readability
- Use TypeScript for all non-trivial projects
- Use optional chaining to simplify null checks
- Use destructuring for cleaner function signatures
- Handle errors at appropriate levels (don't swallow errors)
- Use
=== instead of == for comparisons
- Use ESLint + Prettier for consistent code style
Fetch MDN and TypeScript docs for exact syntax, browser compatibility, and new features before implementing.
1---2name: js-modern3description: Write modern JavaScript and TypeScript — ES6+ features, async/await, modules, destructuring, optional chaining, TypeScript types, and modern tooling. Use when writing JavaScript/TypeScript for Shopify themes, apps, Functions, or Hydrogen storefronts.4---56# Modern JavaScript & TypeScript78## Before writing code910**Fetch live docs**: Web-search `site:developer.mozilla.org javascript` for MDN JavaScript reference. Check `https://www.typescriptlang.org/docs/` for TypeScript documentation.1112## ES6+ Features1314### Arrow Functions1516Concise function syntax with lexical `this`:17- `const add = (a, b) => a + b;`18- Implicit return for single expressions19- No own `this`, `arguments`, `super`, or `new.target`2021### Template Literals2223String interpolation and multi-line strings:24- `` `Hello, ${name}!` ``25- Tagged templates for DSLs2627### Destructuring2829Extract values from objects/arrays:30- `const { name, price } = product;`31- `const [first, ...rest] = items;`32- Default values: `const { name = 'Unknown' } = product;`33- Nested: `const { address: { city } } = customer;`3435### Spread / Rest3637- Spread: `[...arr1, ...arr2]`, `{ ...obj1, ...obj2 }`38- Rest: `function(...args) {}`, `const { a, ...rest } = obj;`3940### Modules (ES Modules)4142- `import { func } from './module.js';`43- `export const value = 42;` / `export default class {}`44- Dynamic: `const mod = await import('./lazy.js');`4546### Optional Chaining & Nullish Coalescing4748- `obj?.property?.nested` — short-circuits to `undefined` if any part is nullish49- `value ?? defaultValue` — returns right side only if left is `null`/`undefined` (not falsy)5051## Async Patterns5253### Promises5455- `new Promise((resolve, reject) => { ... })`56- `.then()`, `.catch()`, `.finally()`57- `Promise.all()`, `Promise.allSettled()`, `Promise.race()`, `Promise.any()`5859### Async/Await6061- `async function fetchData() { const data = await fetch(url); }`62- Error handling with try/catch63- Parallel: `const [a, b] = await Promise.all([fetchA(), fetchB()]);`6465### Fetch API6667```javascript68const response = await fetch(url, {69 method: 'POST',70 headers: { 'Content-Type': 'application/json' },71 body: JSON.stringify(data),72});73const result = await response.json();74```7576## TypeScript7778### Type Annotations7980- `let name: string = 'Product';`81- `function getPrice(id: number): Promise<number> { ... }`82- `const product: Product = { ... };`8384### Interfaces8586```typescript87interface Product {88 id: string;89 title: string;90 handle: string;91 priceRange: {92 minVariantPrice: { amount: string; currencyCode: string };93 };94 variants?: Variant[];95}96```9798### Type Utilities99100- `Partial<T>` — all properties optional101- `Required<T>` — all properties required102- `Pick<T, K>` — subset of properties103- `Omit<T, K>` — exclude properties104- `Record<K, V>` — key-value mapping105- `ReturnType<T>` — extract return type of function106107### Generics108109```typescript110function fetchResource<T>(url: string): Promise<T> {111 return fetch(url).then(res => res.json());112}113const product = await fetchResource<Product>('/api/products/1');114```115116### Enums117118```typescript119enum OrderStatus {120 Pending = 'pending',121 Shipped = 'shipped',122 Completed = 'completed',123}124```125126### Discriminated Unions127128```typescript129type ApiResponse<T> =130 | { status: 'success'; data: T }131 | { status: 'error'; message: string };132```133134## Modern Array Methods135136- `map`, `filter`, `reduce`, `find`, `findIndex`137- `some`, `every` — boolean checks138- `flat`, `flatMap` — array flattening139- `Array.from()`, `Array.isArray()`140- `Object.entries()`, `Object.fromEntries()`, `Object.keys()`, `Object.values()`141- `structuredClone()` — deep clone142143## For Shopify Specifically144145### Theme JavaScript146147- Vanilla JS or minimal libraries — themes should stay lightweight148- Use `<script defer>` and lazy loading for performance149- Access Liquid data via `<script type="application/json">` blocks150- No build step required — Shopify serves assets directly151152### Shopify Functions (Wasm)153154- JavaScript compiled to WebAssembly155- No async (no Promises, no fetch) — synchronous only156- Pure functions: input → output, no side effects157- TypeScript recommended for type safety on I/O schemas158159### Hydrogen / Remix160161- TypeScript by default162- React components with hooks163- Server Components + Client Components164- Remix loaders and actions (server-side)165- Type-safe Storefront API queries166167### App Development168169- Remix server with TypeScript170- Polaris components for admin UI171- App Bridge for embedded app communication172- `@shopify/shopify-app-remix` for auth and session management173174## Best Practices175176- Use `const` by default, `let` when reassignment is needed, never `var`177- Use async/await over raw Promises for readability178- Use TypeScript for all non-trivial projects179- Use optional chaining to simplify null checks180- Use destructuring for cleaner function signatures181- Handle errors at appropriate levels (don't swallow errors)182- Use `===` instead of `==` for comparisons183- Use ESLint + Prettier for consistent code style184185Fetch MDN and TypeScript docs for exact syntax, browser compatibility, and new features before implementing.