How to Remove the Last Character from a String in TypeScript

Building a CSV row in a loop almost always leaves one comma too many at the end. To remove the last character from a string in TypeScript, call slice(0, -1) and keep the value it returns:

const row = "Austin,Dallas,Houston,";
const clean = row.slice(0, -1); // "Austin,Dallas,Houston"

The -1 counts back from the end, and your original string doesn’t change.

Every snippet ran on TypeScript 7.0.2 and Node.js v22.22.2 in strict mode.

How do you remove the last character from a string in TypeScript?

Here’s the city row built in a loop, then trimmed three ways you can copy:

const cities = ["Austin", "Dallas", "Houston"];
let row = "";
for (const city of cities) {
  row += city + ",";
}
console.log(row);                              // trailing comma

console.log(row.slice(0, -1));                 // 1. slice
console.log(row.substring(0, row.length - 1)); // 2. substring
console.log(row.replace(/.$/, ""));            // 3. regex
console.log(row);                              // original unchanged

Output:

Austin,Dallas,Houston,
Austin,Dallas,Houston
Austin,Dallas,Houston
Austin,Dallas,Houston
Austin,Dallas,Houston,
VS Code editor with a TypeScript loop building a city row and three ways to drop the trailing comma, terminal showing the trimmed row three times
All three methods print Austin,Dallas,Houston, and the last line shows the original still ends with a comma.

You’ll want slice(0, -1) most of the time because it’s the shortest. substring() needs length - 1.

The regex /.$/ matches any one final character. To delete a character by value from anywhere in the text, see removing a specific character from a string in TypeScript.

Remove the last character only if it matches

Same city row, but now the comma might not be there, so check first:

function dropTrailing(text: string, char: string): string {
  return text.endsWith(char) ? text.slice(0, -1) : text;
}

console.log(dropTrailing("Austin,Dallas,Houston,", ","));
console.log(dropTrailing("Austin,Dallas,Houston", ","));

// Regex: strip one or more trailing slashes
console.log("/reports/2026//".replace(/\/+$/, ""));

Output:

Austin,Dallas,Houston
Austin,Dallas,Houston
/reports/2026

The first call drops the comma, and the second returns the row untouched. The regex /\/+$/ turns /reports/2026// into /reports/2026.

For swapping that final character for another one, the patterns in replacing characters in a TypeScript string work the same way.

How do you remove the last N characters in TypeScript?

Pass a bigger negative number:

const invoice = "INV-2026-0042.pdf";

console.log(invoice.slice(0, -4));   // drop ".pdf"
console.log(invoice.slice(0, -9));   // drop "-0042.pdf"

console.log(JSON.stringify(invoice.slice(0, -0))); // -0 is just 0

const removeLast = (text: string, n: number): string =>
  n > 0 ? text.slice(0, -n) : text;

console.log(removeLast(invoice, 0));

Output:

INV-2026-0042
INV-2026
""
INV-2026-0042.pdf
VS Code terminal showing an invoice file name with the last 4 and last 9 characters removed, an empty string from slice(0, -0) and a removeLast helper result
slice(0, -4) leaves INV-2026-0042, slice(0, -9) leaves INV-2026, and slice(0, -0) prints an empty string.

Important: -0 is just 0, so slice(0, -n) with n = 0 returns nothing. The removeLast() helper guards against it.

When the part to drop is known text rather than a count, removing a substring from a string in TypeScript is the safer route.

Empty strings and emoji: edge cases for the last character

An empty string and a trailing emoji trip people up. I ran both:

console.log(JSON.stringify("".slice(0, -1)));

const thanks = "Thanks ๐Ÿ‘";
console.log(JSON.stringify(thanks.slice(0, -1)));
console.log(Array.from(thanks).slice(0, -1).join("") + "|");

const team = "Team ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง";
const seg = new Intl.Segmenter("en", { granularity: "grapheme" });
const parts = Array.from(seg.segment(team), (s) => s.segment);
console.log(parts.slice(0, -1).join("") + "|");

Output:

""
"Thanks \ud83d"
Thanks |
Team |
VS Code terminal showing empty-string slice results, a broken half emoji from slice and clean results from Array.from and Intl.Segmenter
Empty input stays empty, slice(0, -1) leaves half of the thumbs-up emoji, and Intl.Segmenter removes the whole family emoji.

The thumbs-up emoji takes two UTF-16 code units, so slice leaves a lone \ud83d behind.

Array.from() splits by code point, which fixes a single emoji. A family emoji joins several, so it needs Intl.Segmenter (ES2022 lib). The array trick is the same one from getting the last element of an array in TypeScript.

Common mistakes when removing the last character

With strict on, an optional parameter can’t call slice() directly. The compiler stops the build:

function dropLast(text?: string): string {
  return text.slice(0, -1);
}

console.log(dropLast("Austin,"));

Compiler output:

drop_undef.ts(2,10): error TS18048: 'text' is possibly 'undefined'.
VS Code showing TypeScript error TS18048 'text' is possibly 'undefined' on text.slice inside a dropLast function
VS Code underlines text and the build fails with TS18048 before any JavaScript runs.

The fix, plus a slip I still see in code reviews:

function dropLast(text?: string): string {
  return text?.slice(0, -1) ?? "";
}
console.log(JSON.stringify(dropLast("Austin,")));
console.log(JSON.stringify(dropLast()));

let path = "/reports/2026/";
path.slice(0, -1);               // result thrown away
console.log(path);
path = path.slice(0, -1);
console.log(path);

Output:

"Austin"
""
/reports/2026/
/reports/2026
  • Optional input: text?.slice(0, -1) ?? "" returns an empty string when nothing is passed.
  • Ignored result: the bare path.slice(0, -1) call changes nothing until you assign it.

If the end might be a space instead, trim it first; see removing spaces from a string in TypeScript.

Other TypeScript string chores I have covered:

Frequently asked questions

How do I remove the last character from a string in TypeScript?

Use text.slice(0, -1) and assign the result. It returns a new string without the final character.

What’s the difference between slice() and substring() here?

slice() accepts negative indexes; substring() treats them as 0, so it needs text.length - 1.

How do I remove the last character only if it’s a comma?

Check first: text.endsWith(",") ? text.slice(0, -1) : text, or use text.replace(/,$/, "").

What happens if the string is empty?

"".slice(0, -1) returns an empty string. It doesn’t throw, so no guard is needed for empty input.

Why does slice(0, -1) break an emoji?

Most emoji use two UTF-16 code units. Split with Array.from() or Intl.Segmenter first.

Where is slice() documented?