truncateWords
Truncates a string to a maximum number of words and appends an ellipsis (or custom suffix).
1/**
2 * Truncates a string to a maximum number of words and appends an ellipsis (or custom suffix).
3 *
4 * @param str - The input string.
5 * @param maxWords - The maximum number of words to keep.
6 * @param ellipsis - Optional string to append if truncated (defaults to '...').
7 * @returns Truncated string with suffix if it exceeded the word limit.
8 */
9export function truncateWords(str: string, maxWords: number, ellipsis: string = '...'): string {
10 if (maxWords < 0) {
11 throw new Error('maxWords must be non-negative');
12 }
13
14 const words = str.trim().split(/\s+/);
15 if (words.length <= maxWords) return str;
16
17 return words.slice(0, maxWords).join(' ') + ellipsis;
18}
Word-Safe Truncation
Prevents breaking in the middle of words, maintaining readability and natural flow.
Custom Suffix Support
Accepts an optional trailing string (e.g.,
'...'
,' [more]'
, etc.), allowing flexibility in UI.Whitespace Tolerance
Uses
.trim()
and a regex split (/\s+/
), ensuring consistent behavior even with irregular spacing.Error-Resistant
Throws early for invalid input (
maxWords < 0
) to avoid silent failures.
Tests | Examples
1test('truncateWords - string with fewer words stays unchanged', () => {
2 expect(truncateWords('Hello world', 5)).toBe('Hello world');
3});
4
5test('truncateWords - string gets truncated to specified word count', () => {
6 expect(truncateWords('The quick brown fox jumps', 3)).toBe('The quick brown...');
7});
8
9test('truncateWords - custom ellipsis', () => {
10 expect(truncateWords('One two three four five', 2, ' (more)')).toBe('One two (more)');
11});
12
13test('truncateWords - exact number of words', () => {
14 expect(truncateWords('Alpha Beta Gamma', 3)).toBe('Alpha Beta Gamma');
15});
16
17test('truncateWords - trims leading/trailing whitespace', () => {
18 expect(truncateWords(' Hello world! ', 1)).toBe('Hello...');
19});
20
21test('truncateWords - zero word limit returns ellipsis only', () => {
22 expect(truncateWords('Some text here', 0)).toBe('...');
23});
24
25test('truncateWords - empty input string', () => {
26 expect(truncateWords('', 5)).toBe('');
27});
28
29test('truncateWords - negative word limit throws', () => {
30 expect(() => truncateWords('text', -2)).toThrow('maxWords must be non-negative');
31});
Common Use Cases
Content Previews
Display the first few words of a blog post, comment, or review in a teaser format.
Text Summaries
Provide a short summary snippet for long user-generated input fields.
Truncated Descriptions
Constrain descriptions to a word limit in grids, lists, or notification areas.
Mobile Optimizations
Improve UX on smaller devices by reducing verbose text in tight layouts.
Search Engine Results Emulation
Mimic how Google or other engines preview content snippets by limiting word count.