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
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:
.indexOf(" ")to find the space, and keep the position it gives you..slice()from the start up to the space, that’s the first name..slice()from just past the space to the end, that’s the last name.- 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.