Values, Variables, and Basic Types
Naming values with let and const, the basic types, and why you usually let the compiler infer a type instead of writing it out.
Naming values with let and const, the basic types, and why you usually let the compiler infer a type instead of writing it out.
A program that cannot remember anything can only react and forget. To do anything useful — count something, compare two things, build a result up piece by piece — it must hold on to information and refer back to it later.
That is what this lesson is about. By the end you will know the two ways to name a value and which to reach for, the handful of basic types everything else is built from, and why you will write far fewer type annotations than you might expect.
const price = 12.99;Read it right to left. The value 12.99 exists; the name
price is attached to it; writing price from now on gets you
that value.
const price = 12.99;
console.log(price); // 12.99
console.log(price * 100); // 1299The = is not the equals sign from mathematics. In maths,
x = 5 states a fact. Here it performs an action: attach this
name to this value.
There are two ways to declare a name, and the difference is whether it can later point at something else.
const price = 12.99;
price = 14.99;
// Cannot assign to 'price' because it is a constant.let total = 0;
total = total + price; // fineThis name always refers to this value.
A reader seeing const knows the value does not change
anywhere below, which is one fewer thing to track.
That is not stylistic fussiness — it is information the reader gets for free.
This name can be pointed elsewhere.
Reaching for it says "this changes", and the reader should then go looking for where.
Use it when you genuinely mean that, and not by habit.
There is an older keyword, var, which you will meet in code
written years ago. It behaves differently in ways that caused
real bugs, and it has no remaining use. Write const or let.
Four cover nearly everything you will write at first.
const price = 12.99; // number
const name = "Ana Duarte"; // string
const isPaid = true; // boolean
const middleName = null; // nullnumber covers everything numeric — whole numbers and
decimals alike. There is one number type, not two, which is
simpler than most languages and has consequences worth their own
lesson.
string is text. It goes in quotes, and the quotes are what
distinguish text from code: name is a name to look up,
"name" is four characters.
boolean holds true or false and nothing else. Neither
is quoted — true and "true" are different things, one a
boolean and one a five-character string.
null represents a deliberate absence. It is not zero and
not empty text; it means there is no value here, said
explicitly. Its companion undefined gets a lesson of its own,
because the difference between them causes real confusion.
You have not written a single type annotation yet, and every one of those names is typed:
const price = 12.99;
price = "cheap";
// Type 'string' is not assignable to type 'number'.TypeScript worked out that price is a number from the value
you gave it. That is inference, and it is why annotated
TypeScript is far less cluttered than people expect.
You can write the type when you want to:
const price: number = 12.99;Both are correct. The second adds nothing the first did not already establish.
Bad — annotating what is already obvious.
const price: number = 12.99;
const name: string = "Ana Duarte";
const isPaid: boolean = true;
const sizes: number[] = [1920, 1080];Good — letting inference work, and annotating the edges.
const price = 12.99;
const name = "Ana Duarte";
const isPaid = true;
const sizes = [1920, 1080];
function applyDiscount(total: number, percent: number): number {
return total * (1 - percent / 100);
}The first version says twice what the values already say, and every annotation is one more thing to update when something changes — so they drift, and a wrong annotation is worse than none. The second annotates where TypeScript genuinely cannot tell: the inputs to a function, which have no value to look at.
The rule is short, and it is most of what you need for the whole course.
What comes in — annotate
A function's parameters have no value for TypeScript to look at, so it genuinely cannot tell. This is where annotations earn their place.
The middle — leave it alone
Every const and let with a value on the right is already
typed. Restating it says the same thing twice, and the copy
drifts.
What goes out — annotate
A return type is a claim the compiler checks the body
against, which turns a wrong return into an error at the
function rather than at its caller.
One place you must annotate is a name declared without a value:
let selected; // implicitly any - no information
let selected: string; // this is what you meantThere is a difference between const and let beyond
reassignment, and it will matter later:
let status = "pending"; // type: string
const state = "pending"; // type: "pending"Because state can never change, TypeScript records not just
"a string" but which string. That is a literal type — a
type with exactly one possible value.
It looks like a curiosity now. It is the foundation of one of TypeScript's most useful features, where a value is allowed to be one of a small set of specific options rather than any text at all. The unions lesson builds directly on this.
You will read your names far more often than you write them.
The convention is camelCase: lowercase first word, capital on
each word after.
const photoCount = 400;
const isProcessed = false;
const customerEmailAddress = "ana@example.com";Names may contain letters, digits, _ and $, and may not
start with a digit. Some words are reserved by the language and
cannot be used — const, let, class, return and others.
Your editor will colour them differently, which is the clue.
Two habits worth adopting immediately:
Name the meaning, not the type. photoCount rather than
num; customer rather than obj. A name that describes the
type tells you what you could already see.
Prefix booleans with is, has or should. isProcessed,
hasDiscount, shouldRetry. It makes conditions read as
sentences later, and it signals a true-or-false value at a
glance.
NAMING A VALUE
const price = 12.99; cannot be repointed <- prefer
let total = 0; can be reassigned
var older, different, do not use
= is an INSTRUCTION, not a claim of equality
const protects the NAME, not the contents of a value
THE BASIC TYPES
number 12.99, 400 one type for all numbers
string "Ana" text, in quotes
boolean true / false unquoted, and only these two
null a deliberate absence
undefined its companion - a lesson of its own
true and "true" are different things
INFERENCE
const price = 12.99; already a number; nothing to add
const price: number = 12.99; says the same thing twice
ANNOTATE what comes in and goes out of a function
DO NOT restate what the value already shows
MUST a declaration with no value: let x: string;
LITERAL TYPES
let status = "pending"; type is string
const state = "pending"; type is "pending" - exactly that
the basis of unions, later
NAMING
camelCase
name the MEANING, not the type photoCount, not num
booleans: is / has / should isProcessed, hasDiscount
reserved words are coloured differently by your editorYou can now hold on to information, choose between a name that changes and one that does not, and you know that most types arrive without being written. That last point shapes how the rest of this course reads: TypeScript code is mostly ordinary code, with annotations at the boundaries where they earn their place.
Next is Strings and Template Literals, which takes the type you will handle most and does it properly — building text out of values, the operations worth knowing, and why every change to a string produces a new one rather than altering the old.
Before you move on, open your project and declare a few names
with const. Then try to reassign one and read the error. Then
declare let status = "pending" and const state = "pending",
and hover over each in your editor. Seeing string on one and
"pending" on the other is a detail you will meet again in
several lessons, and noticing it now makes those land faster.