0% completed
Variables and Data Types
On This Page
Variables
Data Types
Primitive Types
Complex Types
Allowing null and undefined
any and unknown
Type Assertions
Type Annotations
Type Inference
Key Takeaways
An order in an online store holds an order code, a quantity, a customer, a list of prices, and a tracking code that may not exist yet. Describing those values correctly takes variables and the basic data types of TypeScript, together with annotations and inference.
Variables
TypeScript declares variables with let, const, or var, just as JavaScript does, and it adds optional type annotations for safety and predictability:
letdeclares a variable that can be reassigned. Use it for values that change over time, such as counters or state in UI frameworks.constdeclares a variable that cannot be reassigned. Use it for configuration values and for anything else that should not change.varis legacy syntax. It is similar tolet, but its scope is the whole function instead of the block.
let quantity: number = 5; // A variable with type number const orderCode: string = "A-100"; // A constant with type string let customerName = "Alice"; // Inferred as string
Use const unless the variable needs to be reassigned, because the compiler then rejects any accidental reassignment with error TS2588: Cannot assign to 'orderCode' because it is a constant. Note that const protects only the variable, not the object inside it. After const order = { quantity: 3 }, the line order.quantity = 4 is still allowed.
Avoid the variable names name and status at the top level of a file. The compiler includes the type definitions of the browser by default, and they already declare those two names as global variables. A file with no import or export shares that global scope, so let name = "John"; fails with error TS2451: Cannot redeclare block-scoped variable 'name'. This lesson uses other names for that reason.
Data Types
A data type defines what kind of value a variable can hold.
Primitive Types
JavaScript has seven primitive types, and TypeScript uses the same seven:
stringrepresents text.numberrepresents both integers and floating-point numbers.booleanrepresents true or false.nullandundefinedindicate the absence of a value.symbolrepresents a unique and immutable value.bigintrepresents integers too large fornumberto hold exactly. For example,9007199254740993nkeeps its value, but the number9007199254740993prints as9007199254740992.
Complex Types
Three more types describe values that hold other values:
- Arrays hold a collection of elements of one type.
- Tuples are arrays with a fixed number of elements, where each position has its own type.
- Objects hold key-value pairs.
const prices: number[] = [20, 5]; const buyer: { name: string; age: number } = { name: "Bob", age: 30 }; const coordinates: [number, number] = [10, 20];
Use these types to enforce structure, especially when you handle structured data from an API. The tuple rule has one exception. The compiler rejects a third element in the initial value and rejects a read of coordinates[2], but it allows coordinates.push(30), which really does make the array longer at runtime.
Allowing null and undefined
In strict mode, null and undefined are not part of any other type, so a string variable cannot hold them:
let trackingCode: string = null;
tracking.ts(1,5): error TS2322: Type 'null' is not assignable to type 'string'.
To allow them, say so in the type with | null or | undefined. The | symbol means "or":
let trackingCode: string | null = null; // A string or null
any and unknown
Two types accept every value, and they treat it in opposite ways. With any, the compiler stops checking the value, so a mistake appears only at runtime. With unknown, the compiler refuses every use until you prove what the value is:
const anyValue: any = 42; anyValue.toUpperCase(); // Compiles, then throws a TypeError at runtime const unknownValue: unknown = "hello"; unknownValue.toUpperCase(); // Error if (typeof unknownValue === "string") { console.log(unknownValue.toUpperCase()); // Allowed: the check proves it is a string }
values.ts(5,1): error TS18046: 'unknownValue' is of type 'unknown'.
Prefer unknown when you do not know the type of a value, because it keeps the checks that any removes.
Type Assertions
Sometimes you know more about a value than the compiler can infer. A type assertion, written with as, tells the compiler to treat a value as a specific type:
const someValue: unknown = "Hello, World!"; const stringLength: number = (someValue as string).length;
An assertion is only an instruction to the compiler. It does not convert the value, and it adds no check at runtime. If someValue held the number 42, someValue as string would still compile, and the value would still be a number when the program ran. The chapter on advanced types covers assertions in more detail.
Type Annotations
You met annotations in the previous lesson. They are explicit types on variables, function parameters, and return values, and they let the compiler catch errors during development:
let customerEmail: string = "alice@example.com"; // Variable annotation function greet(customer: string): string { // Parameter and return annotations return `Hello, ${customer}`; }
Annotate the return type when a function is part of what other code depends on. The compiler then checks the function body against your stated intention, instead of inferring whatever the body happens to return. This matters most in libraries and frameworks, whose users need to see what types of values are expected.
Type Inference
Type inference works at every project size, and it saves you from annotating each variable. The compiler infers variable types from assignments, and it also infers the return type of a function from its return statements:
let confirmation = "Thank you!"; // Inferred as string function multiply(a: number, b: number) { return a * b; // The return type is inferred as number }
The return type of multiply is checked at each call, even though nobody wrote it. For a small internal function, this inference is usually enough.
Key Takeaways
constprevents reassignment, but it does not freeze an object.nullandundefinedmust be allowed explicitly in strict mode.- Prefer
unknowntoany, and remember thatasconverts nothing. - Annotate the return type of a function that other code depends on, and let the compiler infer the types of small internal functions.
Reading Progress
0%
On This Page
Variables
Data Types
Primitive Types
Complex Types
Allowing null and undefined
any and unknown
Type Assertions
Type Annotations
Type Inference
Key Takeaways