Skip to main content

Strings

Introduction​

Strings are sequences of characters that represent text . They're one of the most fundamental and frequently used data types in programming. Whether you're displaying messages to users, processing form input, working with file names, or handling data from APIs, you're working with strings.

In TypeScript, strings have the same powerful methods as JavaScript, but with the added benefit of type safety . TypeScript ensures you're calling the right methods and passing the correct types of arguments, preventing common string-related bugs.

Why Strings Matter​

Think about all the text in a program:

  • User names and messages
  • Error messages and notifications
  • File paths and URLs
  • Email addresses and phone numbers
  • Product descriptions and reviews
  • Search queries and filters

Strings are everywhere! Mastering string manipulation is essential for any developer.

TypeScript's String Type Safety​

JavaScript (no type checking):

function greet(name) {
return name.toUpperCase(); // What if name is not a string?
}

greet("Alice"); // βœ… "ALICE"
greet(123); // πŸ’₯ Runtime error: toUpperCase is not a function

TypeScript (with type checking):

function greet(name: string): string {
return name.toUpperCase();
}

greet("Alice"); // βœ… "ALICE"
// greet(123); // ❌ Compile error: Argument of type 'number' is not assignable

Strings Are Immutable​

An important concept: strings cannot be changed after they're created . Instead, string methods create and return new strings :

let original: string = "Hello";
let modified: string = original.toUpperCase();

console.log(original); // "Hello" - unchanged!
console.log(modified); // "HELLO" - new string

// This doesn't change the string:
original[0] = "J";
console.log(original); // Still "Hello" (not "Jello")

Creating Strings​

TypeScript supports three ways to create strings:

Single Quotes​

let greeting: string = 'Hello, World!';
let message: string = 'It\'s a beautiful day'; // Escape single quote with \

Double Quotes​

let greeting: string = "Hello, World!";
let message: string = "She said \"Hello\""; // Escape double quote with \

Template Literals (Backticks)​

The most powerful way - supports interpolation and multiline strings:

let name: string = "Alice";
let age: number = 25;

// String interpolation
let message: string = `Hello, ${name}! You are ${age} years old.`;
console.log(message); // "Hello, Alice! You are 25 years old."

// Expressions inside ${}
let calculation: string = `5 + 3 = ${5 + 3}`;
console.log(calculation); // "5 + 3 = 8"

// Multiline strings
let poem: string = `Roses are red,
Violets are blue,
TypeScript is awesome,
And so are you!`;

Which should you use?

  • Use template literals (backticks) for most cases, especially with interpolation
  • Single or double quotes are fine for simple strings without interpolation
  • Be consistent within your codebase

String Properties​

Length Property​

Get the number of characters in a string:

let text: string = "Hello";
console.log(text.length); // 5

let empty: string = "";
console.log(empty.length); // 0

let sentence: string = "TypeScript is great!";
console.log(sentence.length); // 20

// Useful for validation
function isValidPassword(password: string): boolean {
return password.length >= 8;
}

console.log(isValidPassword("abc123")); // false
console.log(isValidPassword("abc12345")); // true

Note: Emojis and special characters can have unexpected lengths:

let emoji: string = "πŸ‘‹";
console.log(emoji.length); // 2 (not 1!) - because of how Unicode works

let flag: string = "πŸ‡ΊπŸ‡Έ";
console.log(flag.length); // 4 (flag emojis are actually two emojis combined)

String Methods​

Case Conversion​

toUpperCase()​

Converts all characters to uppercase:

let text: string = "Hello World";
let upper: string = text.toUpperCase();
console.log(upper); // "HELLO WORLD"

// Useful for case-insensitive comparisons
function compareIgnoreCase(str1: string, str2: string): boolean {
return str1.toUpperCase() === str2.toUpperCase();
}

console.log(compareIgnoreCase("Hello", "HELLO")); // true
console.log(compareIgnoreCase("Hello", "Goodbye")); // false

toLowerCase()​

Converts all characters to lowercase:

let text: string = "Hello World";
let lower: string = text.toLowerCase();
console.log(lower); // "hello world"

// Normalize user input
function normalizeEmail(email: string): string {
return email.toLowerCase().trim();
}

console.log(normalizeEmail(" Alice@EMAIL.COM ")); // "alice@email.com"

Trimming Whitespace​

trim()​

Removes whitespace from both ends:

let messy: string = " Hello World ";
let clean: string = messy.trim();
console.log(clean); // "Hello World"
console.log(clean.length); // 11 (vs original 17)

// Cleaning user input
function sanitizeInput(input: string): string {
return input.trim();
}

console.log(sanitizeInput(" Alice ")); // "Alice"

trimStart() / trimEnd()​

Remove whitespace from one end only:

let text: string = " Hello World ";

console.log(text.trimStart()); // "Hello World "
console.log(text.trimEnd()); // " Hello World"

Searching Within Strings​

includes()​

Check if a string contains a substring:

let text: string = "Hello World";

console.log(text.includes("World")); // true
console.log(text.includes("world")); // false (case-sensitive!)
console.log(text.includes("Hello")); // true
console.log(text.includes("Goodbye")); // false

// Case-insensitive search
function containsIgnoreCase(text: string, search: string): boolean {
return text.toLowerCase().includes(search.toLowerCase());
}

console.log(containsIgnoreCase("Hello World", "world")); // true

startsWith() / endsWith()​

Check the beginning or end of a string:

let filename: string = "document.pdf";

console.log(filename.startsWith("doc")); // true
console.log(filename.endsWith(".pdf")); // true
console.log(filename.endsWith(".docx")); // false

// Validate file types
function isPDFFile(filename: string): boolean {
return filename.toLowerCase().endsWith(".pdf");
}

console.log(isPDFFile("report.PDF")); // true
console.log(isPDFFile("report.doc")); // false

indexOf()​

Find the position of a substring (returns -1 if not found):

let text: string = "Hello World";

console.log(text.indexOf("World")); // 6
console.log(text.indexOf("o")); // 4 (first occurrence)
console.log(text.indexOf("goodbye")); // -1 (not found)

// Check if substring exists
if (text.indexOf("World") !== -1) {
console.log("Found 'World' in the string");
}

// Better way (more modern):
if (text.includes("World")) {
console.log("Found 'World' in the string");
}

lastIndexOf()​

Find the last occurrence:

let text: string = "Hello World, Hello TypeScript";

console.log(text.indexOf("Hello")); // 0 (first occurrence)
console.log(text.lastIndexOf("Hello")); // 13 (last occurrence)

Extracting Substrings​

slice()​

Extract a portion of a string:

let text: string = "Hello World";

// slice(start, end) - end is not included
console.log(text.slice(0, 5)); // "Hello"
console.log(text.slice(6, 11)); // "World"
console.log(text.slice(6)); // "World" (from index 6 to end)

// Negative indices count from the end
console.log(text.slice(-5)); // "World" (last 5 characters)
console.log(text.slice(-5, -1)); // "Worl"

// Extract file extension
function getFileExtension(filename: string): string {
const dotIndex = filename.lastIndexOf(".");
if (dotIndex === -1) return "";
return filename.slice(dotIndex + 1);
}

console.log(getFileExtension("document.pdf")); // "pdf"
console.log(getFileExtension("archive.tar.gz")); // "gz"
console.log(getFileExtension("README")); // ""

substring()​

Similar to slice, but doesn't support negative indices:

let text: string = "Hello World";

console.log(text.substring(0, 5)); // "Hello"
console.log(text.substring(6)); // "World"

// Negative values treated as 0
console.log(text.substring(-5)); // "Hello World" (not "World")

Recommendation: Use slice() - it's more flexible and intuitive.


Replacing Content​

replace()​

Replace the first occurrence:

let text: string = "Hello World";
let newText: string = text.replace("World", "TypeScript");
console.log(newText); // "Hello TypeScript"

// Only replaces first occurrence
let repeated: string = "cat cat cat";
console.log(repeated.replace("cat", "dog")); // "dog cat cat"

replaceAll()​

Replace all occurrences:

let repeated: string = "cat cat cat";
console.log(repeated.replaceAll("cat", "dog")); // "dog dog dog"

// Use with regex for more power
let text: string = "Hello World 123";
console.log(text.replaceAll(/\d/g, "X")); // "Hello World XXX"

Splitting and Joining​

split()​

Convert string to array:

let sentence: string = "I love TypeScript";
let words: string[] = sentence.split(" ");
console.log(words); // ["I", "love", "TypeScript"]

// Split into characters
let word: string = "Hello";
let chars: string[] = word.split("");
console.log(chars); // ["H", "e", "l", "l", "o"]

// CSV parsing
let csv: string = "Alice,25,Engineer";
let data: string[] = csv.split(",");
console.log(data); // ["Alice", "25", "Engineer"]

// Limit the number of splits
let text: string = "a-b-c-d-e";
console.log(text.split("-", 3)); // ["a", "b", "c"]

Array join()​

Convert array back to string:

let words: string[] = ["Hello", "World"];
let sentence: string = words.join(" ");
console.log(sentence); // "Hello World"

let path: string[] = ["users", "alice", "documents"];
let fullPath: string = path.join("/");
console.log(fullPath); // "users/alice/documents"

Template Literals​

Template literals are the most powerful way to work with strings in TypeScript.

String Interpolation​

Embed expressions directly in strings:

let name: string = "Alice";
let age: number = 25;
let city: string = "London";

let intro: string = `My name is ${name}. I am ${age} years old and I live in ${city}.`;
console.log(intro);
// "My name is Alice. I am 25 years old and I live in London."

// Expressions work too
let a: number = 5;
let b: number = 3;
console.log(`${a} + ${b} = ${a + b}`); // "5 + 3 = 8"

// Function calls
function getGreeting(): string {
return "Hello";
}

console.log(`${getGreeting()}, World!`); // "Hello, World!"

Multiline Strings​

No need for \n:

let poem: string = `
Roses are red,
Violets are blue,
TypeScript is awesome,
And so are you!
`;

console.log(poem);

// HTML templates
let html: string = `
<div class="card">
<h2>Welcome</h2>
<p>This is a template literal</p>
</div>
`;

Tagged Templates (Advanced)​

You can process template literals with functions:

function highlight(strings: TemplateStringsArray, ...values: any[]): string {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<mark>${values[i]}</mark>` : "");
}, "");
}

let name: string = "Alice";
let age: number = 25;
let result: string = highlight`Name: ${name}, Age: ${age}`;
console.log(result);
// "Name: <mark>Alice</mark>, Age: <mark>25</mark>"

TypeScript String Features​

String Literal Types​

Restrict a string to specific values:

type Color = "red" | "green" | "blue";

function setColor(color: Color): void {
console.log(`Setting color to ${color}`);
}

setColor("red"); // βœ…
setColor("green"); // βœ…
// setColor("yellow"); // ❌ Error: Argument of type '"yellow"' is not assignable

Template Literal Types​

Create types from template strings:

type Greeting = `Hello, ${string}!`;

let greeting1: Greeting = "Hello, World!"; // βœ…
let greeting2: Greeting = "Hello, Alice!"; // βœ…
// let greeting3: Greeting = "Hi, World!"; // ❌ Error

// More complex example
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type Endpoint = "/users" | "/posts" | "/comments";
type APIRoute = `${HTTPMethod} ${Endpoint}`;

let route1: APIRoute = "GET /users"; // βœ…
let route2: APIRoute = "POST /posts"; // βœ…
// let route3: APIRoute = "GET /other"; // ❌ Error

Common String Patterns​

Validation​

function isValidEmail(email: string): boolean {
return email.includes("@") && email.includes(".");
}

function isValidURL(url: string): boolean {
return url.startsWith("http://") || url.startsWith("https://");
}

function hasMinimumLength(text: string, minLength: number): boolean {
return text.trim().length >= minLength;
}

Formatting​

function capitalize(text: string): string {
if (text.length === 0) return text;
return text[0].toUpperCase() + text.slice(1).toLowerCase();
}

console.log(capitalize("hello")); // "Hello"
console.log(capitalize("WORLD")); // "World"
console.log(capitalize("tYpEsCrIpT")); // "Typescript"

function titleCase(text: string): string {
return text
.split(" ")
.map(word => capitalize(word))
.join(" ");
}

console.log(titleCase("hello world")); // "Hello World"

Truncation​

function truncate(text: string, maxLength: number): string {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength - 3) + "...";
}

console.log(truncate("This is a long string", 10)); // "This is..."
console.log(truncate("Short", 10)); // "Short"

Concepts​

Quick Reference​

// Creating strings
let single: string = 'Hello';
let double: string = "World";
let template: string = `Hello ${name}`;

// Length
"Hello".length // 5

// Case
"Hello".toUpperCase() // "HELLO"
"Hello".toLowerCase() // "hello"

// Trimming
" Hello ".trim() // "Hello"
" Hello ".trimStart() // "Hello "
" Hello ".trimEnd() // " Hello"

// Searching
"Hello".includes("ell") // true
"Hello".startsWith("Hel") // true
"Hello".endsWith("lo") // true
"Hello".indexOf("l") // 2

// Extracting
"Hello".slice(1, 4) // "ell"
"Hello".substring(1, 4) // "ell"

// Replacing
"Hello".replace("l", "L") // "HeLlo"
"Hello".replaceAll("l", "L") // "HeLLo"

// Splitting
"a,b,c".split(",") // ["a", "b", "c"]
"Hello".split("") // ["H", "e", "l", "l", "o"]

Examples​

// Email validator
function validateEmail(email: string): boolean {
email = email.trim().toLowerCase();
return email.includes("@") &&
email.indexOf("@") > 0 &&
email.indexOf("@") < email.length - 1;
}

// URL builder
function buildURL(base: string, path: string, params: Record<string, string>): string {
let url = base + path;
const queryString = Object.entries(params)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
return queryString ? `${url}?${queryString}` : url;
}

console.log(buildURL("https://api.com", "/users", { id: "123", name: "Alice" }));
// "https://api.com/users?id=123&name=Alice"

// Slugify (convert to URL-friendly format)
function slugify(text: string): string {
return text
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, "")
.replace(/[\s_-]+/g, "-")
.replace(/^-+|-+$/g, "");
}

console.log(slugify("Hello World!")); // "hello-world"
console.log(slugify("TypeScript is Great")); // "typescript-is-great"

Challenges​

1. Full Name Length​

  • Create a string variable with your full name.
  • Print the length of the string.
  • Create a function that returns the length of any string.
πŸ’‘ Show Answer
let fullName: string = "Alice Johnson";
console.log(fullName.length); // 13

// Function version
function getStringLength(text: string): number {
return text.length;
}

console.log(getStringLength("Hello World")); // 11
console.log(getStringLength("")); // 0

// With validation
function getValidLength(text: string | null | undefined): number {
if (!text) return 0;
return text.length;
}

console.log(getValidLength("Hello")); // 5
console.log(getValidLength(null)); // 0
console.log(getValidLength(undefined)); // 0

// Count without spaces
function getLengthWithoutSpaces(text: string): number {
return text.replace(/\s/g, "").length;
}

console.log(getLengthWithoutSpaces("Hello World")); // 10


2. Case Conversion​

  • Convert the string "TypeScript" to uppercase.
  • Convert it to lowercase.
  • Create a function that toggles between upper and lower case.
πŸ’‘ Show Answer
let language: string = "TypeScript";

console.log(language.toUpperCase()); // "TYPESCRIPT"
console.log(language.toLowerCase()); // "typescript"

// Toggle case function
function toggleCase(text: string): string {
return text
.split("")
.map(char =>
char === char.toUpperCase()
? char.toLowerCase()
: char.toUpperCase()
)
.join("");
}

console.log(toggleCase("Hello World")); // "hELLO wORLD"
console.log(toggleCase("TypeScript")); // "tYPEsCRIPT"

// Title case
function toTitleCase(text: string): string {
return text
.toLowerCase()
.split(" ")
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}

console.log(toTitleCase("hello world")); // "Hello World"
console.log(toTitleCase("typescript is great")); // "Typescript Is Great"

3. Trim Whitespace​

  • Take the string " Hello World " and remove whitespace from both ends.
  • Create functions to trim only the start or only the end.
  • Demonstrate the difference between each method.
πŸ’‘ Show Answer
let messy: string = " Hello World ";

console.log(messy.trim()); // "Hello World"
console.log(messy.trimStart()); // "Hello World "
console.log(messy.trimEnd()); // " Hello World"

// Show the difference with length
console.log("Original length:", messy.length); // 17
console.log("After trim:", messy.trim().length); // 11
console.log("After trimStart:", messy.trimStart().length); // 14
console.log("After trimEnd:", messy.trimEnd().length); // 14

// Clean user input function
function cleanInput(input: string): string {
return input.trim();
}

console.log(cleanInput(" alice@email.com ")); // "alice@email.com"

// Remove all whitespace
function removeAllWhitespace(text: string): string {
return text.replace(/\s/g, "");
}

console.log(removeAllWhitespace(" Hello World ")); // "HelloWorld"

// Normalize whitespace (multiple spaces to single)
function normalizeWhitespace(text: string): string {
return text.trim().replace(/\s+/g, " ");
}

console.log(normalizeWhitespace("Hello World Today")); // "Hello World Today"


  • Check if "banana" contains "na".
  • Find the first position of "na" in "banana".
  • Count how many times "na" appears in "banana".
πŸ’‘ Show Answer
let fruit: string = "banana";

// Check if contains
console.log(fruit.includes("na")); // true

// Find first position
console.log(fruit.indexOf("na")); // 2

// Count occurrences
function countOccurrences(text: string, search: string): number {
let count = 0;
let position = 0;

while ((position = text.indexOf(search, position)) !== -1) {
count++;
position += search.length;
}

return count;
}

console.log(countOccurrences("banana", "na")); // 2
console.log(countOccurrences("mississippi", "ss")); // 2
console.log(countOccurrences("hello", "l")); // 2

// Alternative with split
function countOccurrencesAlt(text: string, search: string): number {
return text.split(search).length - 1;
}

console.log(countOccurrencesAlt("banana", "na")); // 2

// Case-insensitive search
function includesIgnoreCase(text: string, search: string): boolean {
return text.toLowerCase().includes(search.toLowerCase());
}

console.log(includesIgnoreCase("Hello World", "WORLD")); // true

5. Extract Substring​

  • Extract "Script" from "JavaScript" using slice.
  • Get the first 4 characters of "JavaScript".
  • Get the last 6 characters of "JavaScript".
πŸ’‘ Show Answer
let language: string = "JavaScript";

// Extract "Script"
console.log(language.slice(4)); // "Script"
console.log(language.slice(4, 10)); // "Script"

// First 4 characters
console.log(language.slice(0, 4)); // "Java"

// Last 6 characters
console.log(language.slice(-6)); // "Script"
console.log(language.slice(language.length - 6)); // "Script"

// Extract middle portion
console.log(language.slice(2, 8)); // "vaScri"

// Get file extension
function getExtension(filename: string): string {
const dotIndex = filename.lastIndexOf(".");
if (dotIndex === -1) return "";
return filename.slice(dotIndex + 1);
}

console.log(getExtension("document.pdf")); // "pdf"
console.log(getExtension("photo.jpg")); // "jpg"
console.log(getExtension("archive.tar.gz")); // "gz"
console.log(getExtension("README")); // ""

// Get filename without extension
function removeExtension(filename: string): string {
const dotIndex = filename.lastIndexOf(".");
if (dotIndex === -1) return filename;
return filename.slice(0, dotIndex);
}

console.log(removeExtension("document.pdf")); // "document"
console.log(removeExtension("README")); // "README"


6. Split Into Words​

  • Split "I love coding" into an array of words.
  • Join the words back with a different separator.
  • Reverse the order of words.
πŸ’‘ Show Answer
let sentence: string = "I love coding";

// Split into words
let words: string[] = sentence.split(" ");
console.log(words); // ["I", "love", "coding"]

// Join with different separator
console.log(words.join("-")); // "I-love-coding"
console.log(words.join(", ")); // "I, love, coding"
console.log(words.join("")); // "Ilovecoding"

// Reverse word order
let reversed: string = words.reverse().join(" ");
console.log(reversed); // "coding love I"

// Split into characters
let word: string = "Hello";
let chars: string[] = word.split("");
console.log(chars); // ["H", "e", "l", "l", "o"]

// CSV parsing
function parseCSV(csv: string): string[][] {
return csv.split("\n").map(line => line.split(","));
}

let data = `Name,Age,City
Alice,25,London
Bob,30,Paris`;

console.log(parseCSV(data));
// [["Name","Age","City"], ["Alice","25","London"], ["Bob","30","Paris"]]

// Word count
function countWords(text: string): number {
return text.trim().split(/\s+/).length;
}

console.log(countWords("Hello World")); // 2
console.log(countWords("I love TypeScript")); // 3

7. Replace Text​

  • Replace "bad" with "good" in "This is bad".
  • Replace all occurrences of "cat" with "dog" in "cat cat cat".
  • Create a function to censor words in a string.
πŸ’‘ Show Answer
// Replace first occurrence
let text1: string = "This is bad";
console.log(text1.replace("bad", "good")); // "This is good"

// Replace all occurrences
let text2: string = "cat cat cat";
console.log(text2.replaceAll("cat", "dog")); // "dog dog dog"

// Censor function
function censorWord(text: string, word: string): string {
const replacement = "*".repeat(word.length);
return text.replaceAll(word, replacement);
}

console.log(censorWord("This is bad", "bad")); // "This is ***"
console.log(censorWord("dog cat dog", "dog")); // "*** cat ***"

// Censor multiple words
function censorWords(text: string, words: string[]): string {
let result = text;
for (const word of words) {
result = censorWord(result, word);
}
return result;
}

console.log(censorWords("bad dog and cat", ["bad", "dog"])); // "*** *** and cat"

// Remove all numbers
function removeNumbers(text: string): string {
return text.replace(/\d/g, "");
}

console.log(removeNumbers("Hello 123 World 456")); // "Hello World "

// Replace with function
function replaceWithLength(text: string): string {
return text.replace(/\w+/g, (match) => match.length.toString());
}

console.log(replaceWithLength("Hello World")); // "5 5"


8. Template Literal Practice​

  • Create a multiline string with your name and a message.
  • Use template literals to build a sentence with multiple variables.
  • Create an HTML string using template literals.
πŸ’‘ Show Answer
// Multiline string
let name: string = "Alice Johnson";
let message: string = `
Hello, my name is ${name}.
I am learning TypeScript.
This is a multiline string!
`;
console.log(message);

// Multiple variables
let firstName: string = "Alice";
let lastName: string = "Johnson";
let age: number = 25;
let city: string = "London";

let bio: string = `${firstName} ${lastName} is ${age} years old and lives in ${city}.`;
console.log(bio);

// HTML template
function createCard(title: string, content: string): string {
return `
<div class="card">
<h2>${title}</h2>
<p>${content}</p>
<button>Read More</button>
</div>
`;
}

console.log(createCard("Welcome", "This is a TypeScript tutorial"));

// Table generator
function createTable(headers: string[], rows: string[][]): string {
return `
<table>
<thead>
<tr>${headers.map(h => `<th>${h}</th>`).join("")}</tr>
</thead>
<tbody>
${rows.map(row =>
`<tr>${row.map(cell => `<td>${cell}</td>`).join("")}</tr>`
).join("")}
</tbody>
</table>
`;
}

let table = createTable(
["Name", "Age"],
[["Alice", "25"], ["Bob", "30"]]
);
console.log(table);

// Expression evaluation
let x: number = 10;
let y: number = 5;
console.log(`${x} + ${y} = ${x + y}`); // "10 + 5 = 15"
console.log(`${x} * ${y} = ${x * y}`); // "10 * 5 = 50"

9. Vowel Counter​

  • Write a function that counts vowels in a string.
  • Make it case-insensitive.
  • Return both vowel count and consonant count.
πŸ’‘ Show Answer
function countVowels(text: string): number {
const vowels = "aeiouAEIOU";
let count = 0;

for (const char of text) {
if (vowels.includes(char)) {
count++;
}
}

return count;
}

console.log(countVowels("Hello World")); // 3
console.log(countVowels("TypeScript")); // 2
console.log(countVowels("AEIOU")); // 5

// With reduce
function countVowelsReduce(text: string): number {
const vowels = "aeiouAEIOU";
return text.split("").reduce((count, char) =>
vowels.includes(char) ? count + 1 : count, 0
);
}

// Count vowels and consonants
function countLetters(text: string): { vowels: number; consonants: number } {
const vowels = "aeiouAEIOU";
const letters = text.replace(/[^a-zA-Z]/g, "");

const vowelCount = letters.split("").filter(char => vowels.includes(char)).length;
const consonantCount = letters.length - vowelCount;

return { vowels: vowelCount, consonants: consonantCount };
}

console.log(countLetters("Hello World!"));
// { vowels: 3, consonants: 7 }

// Get individual vowel counts
function getVowelBreakdown(text: string): Record<string, number> {
const vowels = "aeiou";
const result: Record<string, number> = { a: 0, e: 0, i: 0, o: 0, u: 0 };

for (const char of text.toLowerCase()) {
if (vowels.includes(char)) {
result[char]++;
}
}

return result;
}

console.log(getVowelBreakdown("Hello World"));
// { a: 0, e: 1, i: 0, o: 2, u: 0 }


10. Palindrome Checker​

  • Create a function that checks if a string is a palindrome.
  • Make it case-insensitive and ignore spaces/punctuation.
  • Test with various strings including phrases.
πŸ’‘ Show Answer
function isPalindrome(text: string): boolean {
// Clean the string: lowercase and remove non-alphanumeric
const cleaned = text.toLowerCase().replace(/[^a-z0-9]/g, "");

// Compare with reversed version
const reversed = cleaned.split("").reverse().join("");
return cleaned === reversed;
}

console.log(isPalindrome("racecar")); // true
console.log(isPalindrome("hello")); // false
console.log(isPalindrome("A man a plan a canal Panama")); // true
console.log(isPalindrome("race car")); // true
console.log(isPalindrome("Was it a car or a cat I saw?")); // true

// Alternative implementation
function isPalindromeAlt(text: string): boolean {
const cleaned = text.toLowerCase().replace(/[^a-z0-9]/g, "");
const len = cleaned.length;

for (let i = 0; i < len / 2; i++) {
if (cleaned[i] !== cleaned[len - 1 - i]) {
return false;
}
}

return true;
}

// Find longest palindrome substring
function longestPalindrome(text: string): string {
let longest = "";

for (let i = 0; i < text.length; i++) {
for (let j = i + 1; j <= text.length; j++) {
const substring = text.slice(i, j);
if (isPalindrome(substring) && substring.length > longest.length) {
longest = substring;
}
}
}

return longest;
}

console.log(longestPalindrome("babad")); // "bab" or "aba"
console.log(longestPalindrome("racecar is a racecar")); // "racecar"

// Count palindromes in a sentence
function countPalindromeWords(sentence: string): number {
const words = sentence.toLowerCase().split(/\s+/);
return words.filter(word => isPalindrome(word)).length;
}

console.log(countPalindromeWords("mom and dad saw a racecar")); // 4

Summary​

In this chapter, you learned:

βœ… How to create strings with single quotes, double quotes, and template literals

βœ… String properties like length

βœ… Case conversion with toUpperCase() and toLowerCase()

βœ… Trimming whitespace with trim(), trimStart(), and trimEnd()

βœ… Searching strings with includes(), indexOf(), startsWith(), and endsWith()

βœ… Extracting substrings with slice() and substring()

βœ… Replacing content with replace() and replaceAll()

βœ… Splitting strings into arrays and joining them back

βœ… Template literals for interpolation and multiline strings

βœ… TypeScript string literal types and template literal types

Key Takeaways:

  • Strings are immutable - methods return new strings
  • Template literals are the most powerful and modern way to work with strings
  • TypeScript's type system prevents common string-related bugs
  • String methods are chainable for powerful transformations
  • Always validate and sanitize user input strings
  • Use type-safe string literal types when you need specific string values

Best Practices:

  • Use template literals for string interpolation
  • Always trim user input
  • Use case-insensitive comparisons for user-facing text
  • Validate string format before processing (emails, URLs, etc.)
  • Use descriptive variable names for strings
  • Consider using string literal types for constants

In the next chapter, we'll explore Objects and learn how to structure data with TypeScript's powerful type system!

Continue to Chapter 6: Objects β†’