TLDR
TypeScript has 7 primitive types: string, number, boolean, null, undefined, bigint, and symbol. You use them to tell TypeScript what kind of value a variable holds. You write them in lowercase. TypeScript can often figure out the type for you. But knowing how each one works is key to writing safe and clear code.
What Are Primitive Types?
Primitive types are the simplest building blocks in TypeScript. Every piece of data in your program starts with one.
They hold a single value. They are not objects. You cannot add methods or properties to them directly.
TypeScript has 7 primitive types in total:
| Type | What It Holds |
|---|---|
string |
Text like names, messages, or IDs |
number |
Any number: integers, decimals, negatives |
boolean |
Only true or false
|
null |
An intentional empty value |
undefined |
A value that was never assigned |
bigint |
Very large whole numbers |
symbol |
A unique identifier value |
This article covers all 7. You will use string, number, and boolean the most in everyday TypeScript code.
How to Use the string Type
A string holds text. Use it for names, messages, emails, URLs, and any other text data.
Basic string annotation
let firstName: string = "Alice";
let greeting: string = "Hello, world!";
let empty: string = "";
Three ways to write strings
TypeScript supports the same three string styles as JavaScript:
let single: string = 'Single quotes work fine';
let double: string = "Double quotes work too";
let template: string = `Template literals with ${firstName}`;
Template literals (backticks) let you insert values inside a string with ${}. TypeScript checks the types of those inserted values too.
let age: number = 30;
let message: string = `I am ${age} years old`;
// TypeScript checks that 'age' is compatible here
What TypeScript catches with strings
let name: string = "Alice";
name = 42;
// Error: Type 'number' is not assignable to type 'string'.
name = true;
// Error: Type 'boolean' is not assignable to type 'string'.
Once a variable is typed as string, TypeScript blocks you from putting a number or boolean in it.
Common string operations TypeScript knows about
let word: string = "typescript";
word.toUpperCase(); // string
word.length; // number
word.includes("type"); // boolean
word.split(""); // string[]
TypeScript knows the return type of every built-in string method. This means you get autocomplete and error checking for free.
How to Use the number Type
In TypeScript, number covers all numeric values: whole numbers, decimals, and negative numbers. There is no separate int or float type.
All TypeScript numbers are 64-bit floating-point values under the hood.
Basic number annotation
let age: number = 30;
let price: number = 19.99;
let temperature: number = -5;
let zero: number = 0;
Special number values
let infinity: number = Infinity;
let negInfinity: number = -Infinity;
let notANumber: number = NaN;
All three of these are valid number values in TypeScript.
Number formats TypeScript supports
let decimal: number = 255; // Regular decimal
let hex: number = 0xFF; // Hexadecimal (255)
let binary: number = 0b11111111; // Binary (255)
let octal: number = 0o377; // Octal (255)
All four lines hold the same value: 255. TypeScript accepts all these formats as number.
What TypeScript catches with numbers
let score: number = 100;
score = "one hundred";
// Error: Type 'string' is not assignable to type 'number'.
A common mistake: numbers as strings
let userInput: string = "42"; // This is a string, not a number
let doubled: number = userInput * 2;
// Error: The left-hand side of an arithmetic operation must be
// of type 'any', 'number', 'bigint' or an enum type.
TypeScript stops you from doing math with strings. You need to convert first:
let userInput: string = "42";
let doubled: number = Number(userInput) * 2; // Safe conversion
How to Use the boolean Type
A boolean holds one of only two values: true or false. Use it for flags, toggles, conditions, and yes/no states.
Basic boolean annotation
let isLoggedIn: boolean = true;
let hasPermission: boolean = false;
let isLoading: boolean = false;
Booleans from comparisons
Most of the time you do not write true or false by hand. You get booleans from comparisons:
let age: number = 20;
let isAdult: boolean = age >= 18; // true
let isTeenager: boolean = age < 18; // false
let isExactly20: boolean = age === 20; // true
Booleans in conditions
let isLoggedIn: boolean = true;
if (isLoggedIn) {
console.log("Welcome back!");
} else {
console.log("Please log in.");
}
What TypeScript catches with booleans
let isActive: boolean = true;
isActive = 1;
// Error: Type 'number' is not assignable to type 'boolean'.
isActive = "yes";
// Error: Type 'string' is not assignable to type 'boolean'.
In JavaScript, 1 and "yes" are both truthy. But TypeScript does not let you assign them to a boolean variable. You must use true or false.
How to Use the null Type
null means you are intentionally saying a value is empty or missing. It is a deliberate choice.
let selectedUser: string | null = null;
// No user is selected yet
null on its own
You can type a variable as only null. But this is rarely useful on its own.
let nothing: null = null;
nothing = "hello";
// Error: Type 'string' is not assignable to type 'null'.
null combined with other types
The real power of null is combining it with other types using a union (|):
let username: string | null = null;
// Later, when the user logs in:
username = "Alice"; // Also valid
Working safely with null values
With strict: true, TypeScript forces you to check for null before using a value:
let username: string | null = null;
console.log(username.toUpperCase());
// Error: 'username' is possibly 'null'.
// Fix: Check first
if (username !== null) {
console.log(username.toUpperCase()); // Safe
}
How to Use the undefined Type
undefined means a value was never assigned. TypeScript uses this automatically for uninitialized variables and missing function return values.
let city: string | undefined = undefined;
function findUser(id: number): string | undefined {
if (id === 1) {
return "Alice";
}
return undefined; // No user found
}
The difference between null and undefined
This trips up many developers. Here is the key difference:
null |
undefined |
|
|---|---|---|
| Meaning | "I know there is no value here" | "This has not been set yet" |
| Set by | You, on purpose | TypeScript or JS automatically |
| Common use | Function returns no result | Optional properties, unset variables |
let a: null = null; // You chose to leave this empty
let b: undefined = undefined; // This was never set
console.log(typeof a); // "object" (a JavaScript quirk)
console.log(typeof b); // "undefined"
Note:
typeof nullreturns"object"in JavaScript. This is a long-standing bug in the language. TypeScript is aware of this and handles it correctly in type checks.
How to Use the bigint Type
bigint is for working with very large whole numbers. The regular number type can safely handle integers up to 2^53 - 1 (which is 9,007,199,254,740,991). Anything bigger needs bigint.
let bigNumber: bigint = 9007199254740992n; // Add 'n' at the end
let anotherBig: bigint = BigInt(9007199254740992);
When to use bigint
- Working with large database IDs
- Financial calculations that need exact integer precision
- Cryptography
- Scientific computing with very large numbers
What you cannot do with bigint
You cannot mix bigint and number in operations:
let big: bigint = 100n;
let regular: number = 50;
let result = big + regular;
// Error: Operator '+' cannot be applied to types 'bigint' and 'number'.
You must convert one to match the other:
let big: bigint = 100n;
let regular: number = 50;
let result = big + BigInt(regular); // Convert number to bigint
Important:
bigintonly works when yourtsconfig.jsonhas"target": "ES2020"or higher.
How to Use the symbol Type
symbol creates a completely unique value. No two symbols are ever equal, even if they have the same description.
let id1: symbol = Symbol("id");
let id2: symbol = Symbol("id");
console.log(id1 === id2); // false — they are always unique
When to use symbol
Symbols are mainly used as unique keys for object properties. They prevent name clashes when two pieces of code use the same property name.
const USER_ID = Symbol("userId");
const user = {
[USER_ID]: 123,
name: "Alice"
};
console.log(user[USER_ID]); // 123
In everyday application code, you will rarely use symbol. It is more common in library code and advanced patterns.
Type Annotations vs Type Inference
You do not always have to write the type yourself. TypeScript can figure it out from the value you assign. This is called type inference.
let name = "Alice"; // TypeScript infers: string
let age = 30; // TypeScript infers: number
let active = true; // TypeScript infers: boolean
TypeScript reads the value on the right side and assigns the type automatically.
When should you write the type yourself?
// You SHOULD annotate when declaring without a value
let username: string;
username = "Alice";
// You SHOULD annotate when the type is not obvious
let score: number = calculateScore(); // Makes the return type clear
// You CAN skip annotation when the value is obvious
let count = 0; // No need to write ': number'
A good rule: if the type is obvious from the value, let TypeScript infer it. If the type is not clear, write it yourself.
All 7 Primitive Types at a Glance
// string
let name: string = "Alice";
// number
let age: number = 30;
// boolean
let isActive: boolean = true;
// null
let selected: null = null;
// undefined
let result: undefined = undefined;
// bigint (requires target ES2020+)
let bigId: bigint = 9999999999999999999n;
// symbol
let uniqueKey: symbol = Symbol("key");
Quick Comparison of All Primitive Types
| Type | Example Value | Common Use Case |
|---|---|---|
string |
"hello" |
Names, messages, URLs |
number |
42, 3.14, -1
|
Scores, prices, ages |
boolean |
true, false
|
Flags, toggles, conditions |
null |
null |
Intentional empty value |
undefined |
undefined |
Unset variables, optional returns |
bigint |
9999n |
Very large integers |
symbol |
Symbol("id") |
Unique object property keys |
Common Mistakes with Primitive Types
Mixing types without a union:
let value: string = "hello";
value = 42; // Error: You must use string | number if both are valid
Comparing loosely instead of strictly:
let count: number = 0;
if (count == false) { } // Loose comparison, avoid this
if (count === 0) { } // Strict comparison, TypeScript-friendly
Confusing null and undefined:
// These are different
let a: null = null;
let b: undefined = undefined;
a === b; // false
a == b; // true (loose equality, but TypeScript will warn you)
Writing type names with capital letters:
// Wrong — these are JavaScript wrapper objects, not primitive types
let name: String = "Alice"; // Avoid
let age: Number = 30; // Avoid
let flag: Boolean = true; // Avoid
// Correct — always use lowercase
let name: string = "Alice";
let age: number = 30;
let flag: boolean = true;
Always use lowercase.
stringis the primitive type.String(capital S) is a JavaScript object. They behave differently. Always use the lowercase versions in TypeScript.
FAQ
Q: Does TypeScript have a separate int type for whole numbers?
No. TypeScript uses number for all numeric values including integers and decimals. If you need very large integers, use bigint.
Q: Can a variable hold both a string and a number?
Yes. Use a union type: let value: string | number. We cover union types in detail in a later post.
Q: Should I always annotate my variables with types?
Not always. If TypeScript can infer the type from the value, you do not need to write it. For example, let name = "Alice" is fine without : string. Write annotations when the type is not obvious.
Q: What is the difference between null and undefined in TypeScript?
null means the value is intentionally empty. undefined means the value was never set. Use null when you want to say "there is no value here on purpose." Use undefined for optional or uninitialized values.
Q: Why should I use lowercase string instead of String?
string (lowercase) is the primitive type. String (uppercase) is a JavaScript wrapper object. They are different. Using String can cause unexpected behavior. Always use the lowercase versions.
Q: Does TypeScript have a float type?
No. Both integers and floating-point numbers use the number type. Under the hood, all TypeScript numbers are 64-bit floating-point values.
What You Learned
- TypeScript has 7 primitive types:
string,number,boolean,null,undefined,bigint, andsymbol -
stringholds text,numberholds all numeric values,booleanholdstrueorfalse -
nullis an intentional empty value;undefinedmeans a value was never assigned -
biginthandles integers larger than2^53 - 1and requirestarget: ES2020or higher -
symbolcreates unique values used as object property keys - TypeScript can infer types from values, so you do not always need to write them
- Always use lowercase type names:
string,number,boolean, notString,Number,Boolean
Sources: TypeScript Handbook — Basic Types | TypeScript TSConfig Reference
Top comments (0)