String Number and Boolean Types in TypeScript
TypeScript's string, number, and boolean types map directly to JavaScript primitives. Learn how to use each one, what values they accept, and common mistakes to avoid.
TypeScript has three primitive types: string, number, and boolean. These types match JavaScript's primitive values directly, and each one accepts exactly the values you would expect from JavaScript while rejecting everything else.
The table below shows what each type accepts:
| Type | Accepted values | Example |
|---|---|---|
| string | Text and template literals | "hello" |
| number | Integers, floats, NaN, Infinity | 42, 3.14 |
| boolean | true or false only | true, false |
TypeScript infers these types automatically when you assign a value:
let title = "Learn TypeScript"; // inferred: string
let score = 100; // inferred: number
let isDone = false; // inferred: booleanYou rarely need to annotate primitives on variables because the initial value already makes the type obvious to the compiler. For more on when to annotate, see type annotations in TypeScript.
The String Type
A string holds text. It accepts string literals, template literals, and the result of any expression that evaluates to text.
let firstName: string = "Alice";
let greeting = `Hello, ${firstName}!`;
let shout = firstName.toUpperCase();
console.log(greeting); // "Hello, Alice!"
console.log(shout); // "ALICE"The embedded expression inside the template literal runs at compile time as ordinary JavaScript once compiled, and TypeScript checks that whatever you embed there is a valid expression. All the usual JavaScript string methods work as expected, and TypeScript already knows what type each one returns:
let phrase = "TypeScript";
phrase.toLowerCase(); // returns string
phrase.includes("Type"); // returns boolean
phrase.indexOf("Script"); // returns number
phrase.slice(0, 4); // returns stringBecause TypeScript knows these return types, it also catches mistakes like calling a string method on a value that is not a string:
let count = 5;
count.toLowerCase();The compiler recognizes that count is a number and that numbers do not have a toLowerCase method, so it rejects the call before the code runs instead of letting it crash at runtime.
Property 'toLowerCase' does not exist on type 'number'.The Number Type
The number type covers all JavaScript numeric values. Unlike some languages, TypeScript does not have separate types for integers and floats; one type handles everything.
let integer: number = 42;
let float: number = 3.14;
let hex: number = 0xff; // 255
let binary: number = 0b1010; // 10
let big: number = 1_000_000; // underscores for readabilityThe number type also includes the special values NaN and Infinity, and both are considered valid numbers at the type level:
let result: number = NaN;
let infinite: number = Infinity;
console.log(typeof result); // "number"
console.log(typeof infinite); // "number"TypeScript will not warn you that a variable might end up as NaN the way it warns about null or undefined under strict mode. You need to check for that case yourself at runtime with the Number.isNaN function.
All standard arithmetic produces a number, and TypeScript checks that both sides of an arithmetic operation are actually numeric:
let sum = 10 + 5; // 15
let product = 10 * 5; // 50
let quotient = 10 / 3; // 3.3333...
let remainder = 10 % 3; // 1Mixing in a string breaks that expectation. JavaScript would coerce the string into a number at runtime, but TypeScript treats the multiplication operator as numeric only, so it catches the misuse before the code ever runs:
let count = 5;
count * "2";The compiler rejects this expression outright instead of letting it silently coerce, which is exactly the kind of implicit conversion that causes confusing bugs in plain JavaScript.
The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.TypeScript also knows the return types of Math functions and Number methods, so it can catch a wrong argument type the same way:
let price = 49.99;
Math.round(price); // returns number
price.toFixed(2); // returns string, "49.99"
Number.isInteger(price); // returns booleanThe Boolean Type
A boolean is the simplest of the three primitives covered in this article. It accepts exactly two values, true and false, and the compiler assigns it automatically whenever a variable starts out holding one of those two values.
let isReady: boolean = true;
let hasErrors = false; // inferred: booleanThis is different from plain JavaScript, where truthy and falsy values can stand in for booleans inside a condition. TypeScript's boolean type is strict about the assignment itself, so a number like 1 cannot be assigned to a boolean variable even though it would behave as truthy in a condition:
let isReady: boolean = true;
isReady = 1;Even though 1 behaves as truthy in a JavaScript condition, it is still a number, not a boolean, so the assignment itself fails at compile time:
Type 'number' is not assignable to type 'boolean'.Comparison and logical operators produce boolean values automatically, so you rarely need to annotate a variable that receives the result of a comparison:
let isGreater = 10 > 5; // true
let isEqual = "a" === "b"; // false
let isValid = password.length >= 8; // inferred: booleanAvoid the Wrapper Types
JavaScript has wrapper objects, capitalized String, Number, and Boolean, that are different from the lowercase primitives. Never use these capitalized names as TypeScript types.
let wrong: String = "Alice"; // wrong: wrapper object type
let right: string = "Alice"; // right: primitive typeThe wrapper types describe objects, not primitives, and they behave unexpectedly in comparisons because two wrapper objects with the same text are still different objects:
let a = new String("hello");
let b = new String("hello");
console.log(a === b); // false, different object instancesAlways use the lowercase primitive names for annotations. There is no reason to reach for the capitalized wrapper types in ordinary application code, and most linters flag them automatically if they slip into a pull request.
Strict Mode and Null
With TypeScript's strict mode enabled, which is the recommended default for new projects, primitive types do not accept null or undefined:
let title: string = null;The annotation says this variable always holds text, so strict mode treats null as a mismatch just like it would treat a number or a boolean, and stops the assignment before the file even compiles:
Type 'null' is not assignable to type 'string'.This is one of the most valuable protections TypeScript provides. In plain JavaScript, a variable you expected to hold a string can silently become null and crash the program much later; strict mode stops that assignment at the source instead. If a value can genuinely be missing, say so explicitly with a union type that names null as one of the allowed possibilities:
let title: string | null = null; // ok: explicitly allows nullFor more on handling nullable values, see null and undefined in TypeScript.
Common Mistakes
Expecting a Separate Integer Type
TypeScript does not distinguish between integers and floats the way some other languages do, so a beginner might expect the next line to fail and be surprised when it compiles cleanly:
let count: number = 3.7; // perfectly valid, TypeScript has no separate int typeIf your logic depends on whole numbers only, validate that at runtime instead of relying on the type system to enforce it, since the type checker treats every numeric value the same way.
Trusting Unvalidated Input as a Number
Browser input is a common place beginners assume a value is already numeric, but the type system disagrees:
let age: number = prompt("How old are you?");Browser APIs that read user input always return a string or null, never a number, even when the person types digits, so the annotation catches the mismatch immediately instead of letting a broken calculation slip through later:
Type 'string | null' is not assignable to type 'number'.You need to parse and validate that input before treating it as a number. For more on this pattern, see runtime validation in TypeScript.
Rune AI
Key Insights
- Use lowercase
string,number,booleanfor type annotations, never the capitalized wrappers. numbercovers integers, floats,NaN, andInfinity.- TypeScript infers primitive types from initial values so you rarely need explicit annotations on variables.
- Enable strict mode so
nullandundefinedare not silently assignable to primitives. - Template literals, arithmetic, and logical operations all work exactly as they do in JavaScript.
Frequently Asked Questions
Should I use `String`, `Number`, or `Boolean` (capitalized) as types?
Does TypeScript distinguish between integers and floats?
Can I assign `null` or `undefined` to a `string` variable?
Conclusion
String, number, and boolean are the three primitive types you will use in nearly every TypeScript file. They map directly to JavaScript primitives, accept exactly the values you expect, and are inferred automatically from initial values. Always use the lowercase versions for type annotations, never the capitalized wrapper objects. With strict mode enabled, these types keep your code safe from null, undefined, and accidental type mismatches.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.