DEV Community

Cover image for How to Use Primitive Types in TypeScript: string, number, and boolean
Krunal Kanojiya
Krunal Kanojiya

Posted on

How to Use Primitive Types in TypeScript: string, number, and boolean

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 = "";
Enter fullscreen mode Exit fullscreen mode

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}`;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'.
Enter fullscreen mode Exit fullscreen mode

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[]
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Special number values

let infinity: number = Infinity;
let negInfinity: number = -Infinity;
let notANumber: number = NaN;
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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'.
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Booleans in conditions

let isLoggedIn: boolean = true;

if (isLoggedIn) {
  console.log("Welcome back!");
} else {
  console.log("Please log in.");
}
Enter fullscreen mode Exit fullscreen mode

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'.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Note: typeof null returns "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);
Enter fullscreen mode Exit fullscreen mode

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'.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Important: bigint only works when your tsconfig.json has "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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Comparing loosely instead of strictly:

let count: number = 0;

if (count == false) { } // Loose comparison, avoid this
if (count === 0) { }    // Strict comparison, TypeScript-friendly
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Always use lowercase. string is 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, and symbol
  • string holds text, number holds all numeric values, boolean holds true or false
  • null is an intentional empty value; undefined means a value was never assigned
  • bigint handles integers larger than 2^53 - 1 and requires target: ES2020 or higher
  • symbol creates 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, not String, Number, Boolean

Sources: TypeScript Handbook — Basic Types | TypeScript TSConfig Reference

Top comments (0)