or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

date-time-formatting.mddisplay-name-formatting.mdindex.mdintl-instance.mdlist-formatting.mdmessage-formatting.mdnumber-formatting.mdrelative-time-pluralization.mdutility-functions.md
tile.json

list-formatting.mddocs/

List Formatting

Format arrays of items with locale-appropriate conjunctions, disjunctions, and unit formatting. Supports both string lists and rich content with custom rendering through parts-based output.

Capabilities

formatList Function

Formats arrays of items with locale-appropriate conjunction/disjunction patterns.

/**
 * Format arrays with locale-appropriate conjunctions
 * @param opts - Configuration with locale and error handler
 * @param getListFormat - List formatter factory function
 * @param values - Array of string or rich content items
 * @param options - List formatting options for type and style
 * @returns Formatted list as string or rich content array
 */
function formatList<T>(
  opts: {
    locale: string;
    onError: OnErrorFn;
  },
  getListFormat: Formatters['getListFormat'],
  values: readonly (string | T)[],
  options?: FormatListOptions
): string | T | (string | T)[];

formatListToParts Function

Formats lists returning arrays of parts for custom rendering and styling.

/**
 * Format lists returning array of parts for custom rendering
 * @param opts - Configuration with locale and error handler
 * @param getListFormat - List formatter factory function
 * @param values - Array of string or rich content items
 * @param options - List formatting options
 * @returns Array of list parts with types and values
 */
function formatListToParts<T>(
  opts: {
    locale: string;
    onError: OnErrorFn;
  },
  getListFormat: Formatters['getListFormat'],
  values: readonly (string | T)[],
  options?: FormatListOptions
): Part<T | string>[];

Usage Examples:

import { formatList, createFormatters } from "@formatjs/intl";

const config = {
  locale: 'en-US',
  onError: console.error
};

const formatters = createFormatters();

// Basic list formatting (conjunction)
const items = ['apples', 'bananas', 'oranges'];
const conjunctionList = formatList(config, formatters.getListFormat, items);
// Result: "apples, bananas, and oranges"

// Disjunction list
const options = ['coffee', 'tea', 'water'];
const disjunctionList = formatList(config, formatters.getListFormat, options, {
  type: 'disjunction'
});
// Result: "coffee, tea, or water"

// Unit list
const measurements = ['5 meters', '10 kilos', '15 liters'];
const unitList = formatList(config, formatters.getListFormat, measurements, {
  type: 'unit'
});
// Result: "5 meters, 10 kilos, 15 liters"

// Two items
const pair = ['salt', 'pepper'];
const pairList = formatList(config, formatters.getListFormat, pair);
// Result: "salt and pepper"

// Single item
const single = ['onion'];
const singleList = formatList(config, formatters.getListFormat, single);
// Result: "onion"

FormatListOptions Interface

Options for controlling list formatting style and behavior.

type FormatListOptions = Omit<IntlListFormatOptions, 'localeMatcher'>;

interface IntlListFormatOptions {
  /** List type determines conjunction words */
  type?: 'conjunction' | 'disjunction' | 'unit';
  /** List style affects formatting density */
  style?: 'long' | 'short' | 'narrow';
}

Usage Examples:

const items = ['red', 'green', 'blue'];

// Different list types
const conjunction = formatList(config, formatters.getListFormat, items, {
  type: 'conjunction'
});
// Result: "red, green, and blue"

const disjunction = formatList(config, formatters.getListFormat, items, {
  type: 'disjunction'
});
// Result: "red, green, or blue"

const unit = formatList(config, formatters.getListFormat, items, {
  type: 'unit'
});
// Result: "red, green, blue"

// Different styles
const longStyle = formatList(config, formatters.getListFormat, items, {
  style: 'long'
});
// Result: "red, green, and blue"

const shortStyle = formatList(config, formatters.getListFormat, items, {
  style: 'short'
});
// Result: "red, green, & blue" (locale dependent)

const narrowStyle = formatList(config, formatters.getListFormat, items, {  
  style: 'narrow'
});
// Result: "red, green, blue" (minimal separators)

Rich Content List Formatting

Format lists containing rich content elements like React components.

Usage Examples:

// React components in lists
const richItems = [
  'plain text',
  <strong>bold text</strong>,
  <em>italic text</em>
];

const richList = formatList(config, formatters.getListFormat, richItems);
// Result: ["plain text", ", ", <strong>bold text</strong>, ", and ", <em>italic text</em>]

// Custom rich content rendering
const linkItems = [
  'Home',
  { type: 'link', href: '/about', text: 'About' },
  { type: 'link', href: '/contact', text: 'Contact' }
];

const linkList = formatList(config, formatters.getListFormat, linkItems);
// Result: Mixed array of strings and link objects

// Complex rich content
const notificationItems = [
  'New message',
  { type: 'user', name: 'Alice', action: 'liked your post' },
  { type: 'system', message: 'Server maintenance scheduled' }
];

const notifications = formatList(config, formatters.getListFormat, notificationItems, {
  type: 'conjunction'
});

List Parts for Custom Rendering

Use formatListToParts for complete control over list rendering.

Usage Examples:

const items = ['first', 'second', 'third'];
const parts = formatListToParts(config, formatters.getListFormat, items);

// Result: [
//   { type: 'element', value: 'first' },
//   { type: 'literal', value: ', ' },
//   { type: 'element', value: 'second' },
//   { type: 'literal', value: ', and ' },
//   { type: 'element', value: 'third' }
// ]

// Custom rendering with parts
const customRender = parts
  .map((part, index) => {
    if (part.type === 'element') {
      return `<span class="list-item" data-index="${index}">${part.value}</span>`;
    }
    return `<span class="list-separator">${part.value}</span>`;
  })
  .join('');

// Rich content parts
const richItems = ['text', <Button>Click</Button>, 'more text'];
const richParts = formatListToParts(config, formatters.getListFormat, richItems);

// Result: [
//   { type: 'element', value: 'text' },
//   { type: 'literal', value: ', ' },
//   { type: 'element', value: <Button>Click</Button> },
//   { type: 'literal', value: ', and ' },
//   { type: 'element', value: 'more text' }
// ]

// Process parts for different rendering contexts
const processedParts = richParts.map(part => {
  if (part.type === 'element' && typeof part.value === 'object') {
    // Handle React components or other rich content
    return renderRichContent(part.value);
  }
  return part.value;
});

Locale-Specific List Formatting

Different locales use different conjunction and disjunction patterns.

Usage Examples:

const items = ['A', 'B', 'C'];

// English conjunction
const english = formatList(
  { locale: 'en-US', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A, B, and C"

// Spanish conjunction  
const spanish = formatList(
  { locale: 'es-ES', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A, B y C"

// German conjunction
const german = formatList(
  { locale: 'de-DE', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A, B und C"

// French conjunction
const french = formatList(
  { locale: 'fr-FR', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A, B et C"

// Japanese conjunction (different separator pattern)
const japanese = formatList(
  { locale: 'ja-JP', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A、B、C" (no conjunction word)

// Arabic conjunction (right-to-left)
const arabic = formatList(
  { locale: 'ar-SA', onError: console.error },
  formatters.getListFormat,
  items
);
// Result: "A و B و C"

Advanced List Formatting Patterns

Complex list formatting scenarios and edge cases.

Usage Examples:

// Empty list handling
const emptyList = formatList(config, formatters.getListFormat, []);
// Result: ""

// Single item
const singleItem = formatList(config, formatters.getListFormat, ['only']);
// Result: "only"

// Two items (no comma in English)
const twoItems = formatList(config, formatters.getListFormat, ['first', 'second']);
// Result: "first and second"

// Long lists
const longList = formatList(config, formatters.getListFormat, [
  'item1', 'item2', 'item3', 'item4', 'item5', 'item6'
]);
// Result: "item1, item2, item3, item4, item5, and item6"

// Mixed content with nullish values (filtered out)
const mixedList = formatList(
  config, 
  formatters.getListFormat, 
  ['valid', null, 'also valid', undefined, 'last'].filter(Boolean)
);
// Result: "valid, also valid, and last"

// Disjunction with different styles
const disjunctionShort = formatList(config, formatters.getListFormat, items, {
  type: 'disjunction',
  style: 'short'
});
// Result: "A, B, or C" (may vary by locale)

// Unit formatting for measurements
const measurements = ['5kg', '10m', '15°C'];
const unitMeasurements = formatList(config, formatters.getListFormat, measurements, {
  type: 'unit',
  style: 'short'
});
// Result: "5kg, 10m, 15°C"

Integration with Intl Instance

When using createIntl, list formatting methods are available on the instance.

Usage Examples:

import { createIntl } from "@formatjs/intl";

const intl = createIntl({
  locale: 'en-US'
});

// Instance methods
const list = intl.formatList(['a', 'b', 'c']);
// Result: "a, b, and c"

const parts = intl.formatListToParts(['x', 'y', 'z'], {
  type: 'disjunction'
});
// Result: Parts array for "x, y, or z"

// With rich content in React
const richList = intl.formatList([
  'Click',
  <Link to="/home">Home</Link>,
  'or',
  <Link to="/about">About</Link>
]);
// Result: Mixed array with strings and React elements

Part Interface

interface Part<T = string> {
  /** Part type: 'element' for list items, 'literal' for separators */
  type: 'element' | 'literal';
  /** Part value: original item for elements, separator text for literals */
  value: T | string;
}