Truncate StringLoading saved progress…

Truncate String

Truncating a string shortens it to a maximum length and marks the removed tail with a short indicator — usually an ellipsis (...). It is the logic behind a card that shows the first line of an article and trails off, or a file list that keeps long names from breaking the layout. This is a re-implementation of Lodash's _.truncate: the result — text plus the indicator — never exceeds the limit, and you can optionally break on the last whole word instead of mid-character.

Signature

truncateString(
  str: string,
  options?: {
    length?: number;             // max length of the RESULT, default 30
    omission?: string;           // appended where text is cut, default '...'
    separator?: string | RegExp; // if set, back up to the last match
  }
): string

Examples

truncateString('The quick brown fox jumps over the lazy dog');
// 'The quick brown fox jumps o...'  (exactly 30 chars)

truncateString('The quick brown fox', { length: 10 });
// 'The qui...'
// A separator retreats the cut to the last word boundary.
truncateString('hi-diddly-ho there, neighborino', { length: 24, separator: ' ' });
// 'hi-diddly-ho there,...'

// A custom omission — it still counts against the length.
truncateString('The quick brown fox jumps', { length: 20, omission: ' [more]' });
// 'The quick bro [more]'

Notes

  • Length is the ceiling for the whole result — the omission counts against it. Reserve omission.length first, then fill the remaining room with characters from str.
  • Short strings pass through untouched — when str.length is at most length, return str with no omission appended. A string that already fits is never marked.
  • The separator breaks on a boundary — when separator is given (a string or a RegExp), retreat the cut to the last place it matches inside the room, so you never slice a word in half. Without it, the cut is exact.
  • Oversized omission is the one exception — if the omission alone is as long as or longer than length, there is no room for text, so return just the omission (it may exceed length).
  • ASCII only — treat the string as one character per code unit. Multi-byte emoji and combining marks are out of scope here; see the solution for why they need extra care.

FAQ

Why does the result sometimes come out shorter than the length I asked for?
Because length is the maximum, not a target. Truncate first subtracts the omission to find the room for visible characters, and then — if you pass a separator — retreats the cut to the last word boundary inside that room. Both steps can only shorten the result, so a 30-character budget often yields a 24- or 25-character string.
What happens when the omission is longer than the length?
There is no room for any visible text, since room = length minus omission.length is zero or negative. Truncate returns just the omission — even though that string is itself longer than length. This mirrors lodash: length is a best-effort ceiling, and an oversized omission is the one case that breaks it.
How does the separator cut on a word boundary?
After slicing the string down to the room, truncate looks inside that slice for the last place the separator matches — the last space, comma, or whatever pattern you passed — and cuts there, dropping the partial word. A string separator uses lastIndexOf; a RegExp is scanned with the global flag so every match is considered and the final one wins.
Loading editor…