String Handling

Whenever a program deals with text — a name typed into a form, a password, a tweet, the title of a song, a line of a poem — it is working with a string. And the single most important thing to know about a string is this: it is a sequence of characters, laid out in order, one after another, like beads on a thread.

Take the word "HELLO". It isn't one lump — it's the character H, then E, then L, then L, then O, in that exact order. Because a string is an ordered sequence, we can ask sensible questions about it: how long is it? what's the third character? what are the first two letters? can I stick two strings together? This page is a tour of the everyday tools every programmer uses to answer questions like those.

How long is it? — .length

Every string knows its own size. Ask for its .length and you get back the number of characters it contains — letters, digits, spaces and punctuation all count. Press Run:

const name: string = "Ada"; console.log(name.length); // 3 console.log("HELLO".length); // 5 console.log("password123".length); // 11 console.log("Hi there".length); // 8 — the space counts too! console.log("".length); // 0 — the empty string

Notice that .length has no brackets after it — it's a property the string carries, not something you call. This one little number turns out to be the key that unlocks everything else on this page, because it tells us how far we can count.

Picking out one character — indexing

Each character sits at a numbered position called its index, and here is the rule that trips up almost every beginner: counting starts at 0, not 1. So the first character is at index 0, the second at index 1, and so on. Write the index in square brackets after the string — s[i] — to pull out that one character. Study the diagram, then run the code:

const word: string = "STRING"; console.log(word[0]); // "S" — the FIRST character console.log(word[1]); // "T" console.log(word[5]); // "G" — the LAST character console.log(word.length); // 6 console.log(word[word.length - 1]); // "G" — the reliable way to get the last character

Look carefully at that last line. The word has length 6, but its last character lives at index 5 — one less than the length. That gap of one, between "how many" and "the last index", is the source of the classic string bug.

Indexing starts at 0. So for a string s:

That last one is the trap. It feels natural to write s[s.length] to grab the last character — but "STRING" has length 6, and there is no character at index 6 (the valid indices are only 0 to 5). Reaching past the end gives you undefined, and this off-by-one error — being one position out at the very end — is one of the most common bugs in all of programming. Whenever you touch the last character of a string, reach for s.length - 1.

Taking a slice — .slice and .substring

Often you don't want a single character but a chunk of the string — the first three letters, the middle bit, everything after the space. That's called a substring, and you take one with .slice(start, end). It gives you the characters from index start up to but not including end — the same "stops just before" habit you saw with indexing.

const s: string = "programming"; // 0123456789... console.log(s.slice(0, 4)); // "prog" — indices 0,1,2,3 (NOT 4) console.log(s.slice(4, 7)); // "ram" — indices 4,5,6 console.log(s.slice(3)); // "gramming" — leave off the end to go to the finish console.log(s.slice(-3)); // "ing" — a negative start counts from the end

.substring(start, end) does almost exactly the same job and you'll see it a lot too; for everyday, forwards slices the two behave identically. The handy trick to remember is slice(start, end) returns \texttt{end} - \texttt{start} characters — so s.slice(4, 7) gives 7 - 4 = 3 of them.

Joining strings together — concatenation

Gluing strings end-to-end is called concatenation, and you do it with the very same + sign you use to add numbers. With text, though, + doesn't add — it joins. This is how programs build up messages, greet users by name, and stitch together output:

const first: string = "Ada"; const last: string = "Lovelace"; const fullName: string = first + " " + last; // don't forget the space! console.log(fullName); // "Ada Lovelace" const greeting: string = "Hello, " + first + "!"; console.log(greeting); // "Hello, Ada!" console.log("1" + "1"); // "11" — text, so it JOINS, it does not add to 2!

That final line is worth pausing on: "1" + "1" is "11", not 2, because both sides are strings. This is exactly why the difference between a number and a string of digits — a data type question — matters so much.

Changing case — .toUpperCase() and .toLowerCase()

Two more tools you'll use constantly flip a string's case: .toUpperCase() SHOUTS it, .toLowerCase() whispers it. These do have brackets, because you are asking the string to do something and hand back a new string (the original is never changed).

const shout: string = "hello".toUpperCase(); console.log(shout); // "HELLO" console.log("QUIET PLEASE".toLowerCase()); // "quiet please" // A real use: compare answers ignoring case. const answer: string = "PARIS"; console.log(answer.toLowerCase() === "paris"); // true — "PARIS" matches "paris"

That last example is the everyday reason to change case: if a quiz should accept "Paris", "PARIS" and "paris" as the same answer, you lower-case both sides before comparing. Case-changing turns messy human input into a tidy, comparable form.

Looping over every character

Because a string is a sequence with a known .length, you can visit every character in turn with a count-controlled loop. Start the counter at 0 and keep going while i < word.length — that runs i across exactly the valid indices 0 to \texttt{length}-1, with no off-by-one:

const word: string = "cat"; for (let i = 0; i < word.length; i++) { console.log("Character " + i + " is: " + word[i]); }

Once you can walk through the characters, you can process them. Here we count how many times the letter "s" appears in a sentence — a running total that goes up by one each time the loop lands on an s:

const sentence: string = "she sells sea shells"; let count: number = 0; for (let i = 0; i < sentence.length; i++) { if (sentence[i] === "s") { count = count + 1; } } console.log("The letter 's' appears " + count + " times.");

Putting it together: initials, reversing, and a password check

These few tools combine into genuinely useful little programs. Here we build someone's initials by grabbing the first character of each name and upper-casing it:

const first: string = "grace"; const last: string = "hopper"; const initials: string = first[0].toUpperCase() + last[0].toUpperCase(); console.log(initials); // "GH"

To reverse a word, loop through it backwards — start at the last index word.length - 1 and count down to 0 — building up a new string as you go:

const word: string = "stressed"; let reversed: string = ""; for (let i = word.length - 1; i >= 0; i--) { reversed = reversed + word[i]; } console.log(reversed); // "desserts" — a tasty palindrome-ish surprise!

And a first taste of validation — checking a password is long enough. Here we simply compare its .length against a minimum:

function passwordOkay(pw: string): boolean { return pw.length >= 8; } console.log(passwordOkay("cat")); // false — only 3 characters console.log(passwordOkay("sunshine")); // true — exactly 8 console.log(passwordOkay("p@ssw0rd!")); // true — 9 characters

Yes — and forgetting it causes real bugs. The string "Hi there" has length 8, not 7, because the space between the words is a genuine character with its own index (index 2 here). Tabs and even invisible "newline" characters count too. This is why a website that asks you to "enter no spaces" can complain about a password that looks fine to you: to the computer, a sequence of characters is exactly that — every single one of them, visible or not.

It looks like a mistake, but it's deliberate and clever. Deep down, a string is stored in the computer's memory as a row of slots, and the index is really "how far along from the start am I?" The first character is right at the start — zero steps along — so it's index 0. The character at index 3 is three steps from the beginning. Once you think of the index as a distance from the start rather than a position number, counting from 0 suddenly makes perfect sense — and it's why nearly every programming language does it.