Contents

Chapter 4

Strings: Text TypeScript Already Understands

Template literals, joining, measuring, and slicing.

Every string you’ve written so far got joined with +, one piece stuck onto the next. That works, and it’s about to get old. Here’s the tool TypeScript actually gives you for this, plus a few more things a string can do that you haven’t needed yet.

A better way to join text

Wrap a string in backticks instead of quotes, and ${} lets you drop a value right into the middle of it:

const firstName = "Ada";
const lastName = "Lovelace";

const full = `${firstName} ${lastName}`;
console.log(full);
Ada Lovelace

That’s a template literal. Read it left to right like the sentence it’s building: whatever’s outside ${} prints exactly as written, whatever’s inside gets evaluated and dropped in. No +, no juggling where the spaces go, you just write the sentence with blanks in it.

It’s not fussy about what goes in the blanks, either:

const quantity = 2;
const price = 49.5;
const ready = true;

console.log(`${quantity} x ${price}`);
console.log(`Ready: ${ready}`);
2 x 49.5
Ready: true

A number, a boolean, doesn’t matter. Whatever’s inside ${} gets converted to text automatically, the same conversion console.log already does when you hand it a bare value.

How long is it?

console.log(full.length);
12

Ada Lovelace is twelve characters, the space counts as one of them. Notice there’s no parentheses. length is a property, not something you call, you’re not asking the string to do work, you’re reading a fact it already knows about itself.

Positions start at zero

Same rule text always follows: the first character sits at position 0, not 1.

 A   d   a       L   o   v   e   l   a   c   e
 0   1   2   3   4   5   6   7   8   9  10  11

Square brackets get you one character:

console.log(full[0]);
A

Notice what you got back: a string. Not some separate “character” type, just an ordinary string that happens to be one letter long. TypeScript doesn’t split text and characters into two different types the way some languages do, and single quotes and double quotes mean exactly the same thing here, both just make a string. Pick one and stay consistent; this book uses double quotes.

Taking a piece out

.slice() cuts a piece out. Give it a starting position and where to stop:

console.log(full.slice(0, 3));
console.log(full.slice(4));
Ada
Lovelace

The first argument is where to start. The second is where to stop, not how many characters to take, slice(0, 3) gives you positions 0, 1, and 2, and stops before it reaches 3. Leave the second number off and it runs to the end of the string, which is what the second line does.

Neither call changes full. It still holds Ada Lovelace, .slice() hands you a new string and leaves the original exactly as it was.

Exercise 1 · Negative positions

Try full.slice(-8). Read what comes back before you run it, then check.

A negative number counts backward from the end instead of forward from the start, so -8 means “eight characters before the end” rather than a position that doesn’t exist. It’s a shortcut worth knowing, not something to lean on until it’s second nature.

Looking for something

.indexOf() tells you where something is:

console.log(full.indexOf(" "));
3

The space in Ada Lovelace is at position 3, matching the diagram above. It works with longer pieces too, full.indexOf("Lov") gives you 4.

Two more worth knowing

.indexOf() answers where. Sometimes you only want whether:

console.log(full.includes("Love"));
console.log(full.includes("z"));
true
false

.includes() skips straight to yes or no, no position to compare against -1. Reach for .indexOf() when you need to know where something is, .includes() when you only need to know if it’s there at all.

Case matters everywhere you’ve used a string so far, "Ada" and "ada" are different strings as far as TypeScript is concerned. To ignore case on purpose, convert both sides the same way first:

console.log(full.toUpperCase());
console.log(full.toLowerCase());
ADA LOVELACE
ada lovelace

Neither changes full, same as .slice(), you get a new string back and the original is untouched.

Exercise 2 · Find the last character properly

Print full[full.length - 1], you should get e. Then predict full.slice(4, 7) before running it, and check with full.indexOf("ace"). Getting these right in your head first is the actual skill, running them is just confirmation.

Check yourself

1. What does `${quantity} x ${price}` produce if quantity is 2 and price is 49.5?

Not quite. Template literals convert whatever is inside ${} to text automatically. No error, no manual conversion needed.

Yes. Everything outside ${} prints as written, everything inside gets evaluated and converted to text.

Not quite. That would happen with ordinary quotes. Backticks are what turn ${} into a live slot rather than plain text.

2. full.slice(0, 3) on "Ada Lovelace". What comes back?

Yes. The second argument is where slice stops, not how many characters to take. It grabs positions 0, 1, and 2.

Not quite. slice stops before it reaches the second number. Position 3 is never included.

Not quite. slice never throws for a number like this. It just returns the characters in range.

3. full.indexOf("z") when there is no z in the string. What do you get?

Not quite. Dangerous if true, 0 is a real position, the first character. A "not found" answer has to be something that could never be a real one.

Yes. No real position is ever negative, so it can never be confused with a genuine answer.

Not quite. indexOf always returns a number. undefined shows up elsewhere in TypeScript, not here.

Project

An initials formatter

Roughly 30 minutes

Take a full name and print its initials. Start with the name hardcoded in a const, chapter 5 is where the reader gets to type their own.

From Ada Lovelace, produce:

Ada Lovelace
First name: Ada
Last name: Lovelace
Initials: A.L.

The shape of it:

  1. .indexOf(" ") to find the space, and keep the position it gives you.
  2. .slice() from the start up to the space, that’s the first name.
  3. .slice() from just past the space to the end, that’s the last name.
  4. Take character [0] of each, and join everything with a template literal.

Rules: every variable gets a name that says what it holds, and the final line is built with one template literal, not a chain of +.

Stretch: make it work for a middle name, Ada Byron Lovelace giving A.B.L., and notice how quickly this gets awkward with the tools you have. You’re feeling the shape of a loop, which arrives in chapter 8.