Primitive Types in TypeScript
Several core primitive types and specialised types that are essential for specifying application structure and guaranteeing type safety are provided by TypeScript, which builds upon JavaScript’s basic types and improves them with static typing.
Core Primitive Types
The TypeScript type system provides a good representation of the JavaScript primitive types, particularly number, string, and boolean. Typically, the :TypeAnnotation syntax is used when writing type declarations.
Number
JavaScript is essentially limited to a single number type: double-precision 64-bit floating-point values. This type is represented by TypeScript using the number keyword, and it includes both floating-point and integer values. Only numeric values can be stored in variables designated as number, thanks to the type annotation.
Numerical literals can be stated in binary (prefixed with 0b), octal (prefixed with 0o), hexadecimal (prefixed with 0x), and base-10 decimal.
// Core Type: number
let count: number = 5; // Integer value is acceptable
let pi: number = 3.14; // Floating point value
let hexValue: number = 0xFF; // Hexadecimal value
let binaryValue: number = 0b10; // Binary value
// Attempting invalid assignment (results in a compile-time error):
// count = 'hello'; // Error: Type 'string' is not assignable to type 'number'
String
Textual data is represented by the string type, which is basically a series of Unicode characters. Template strings, single quotes, and double quotes can all be used to define string values.
// Core Type: string
let str: string = 'Hello World'; // Single quotes
let doubleStr: string = "TypeScript is great";
let templateStr: string = `I am ${str}`; // Template string example
// Attempting invalid assignment (results in a compile-time error):
// str = 123; // Error: Type 'number' is not assignable to type 'string'
Boolean
The boolean type is the most fundamental data type and is used to assign true or false as logical values.
// Core Type: boolean
let isTrue: boolean = true;
let isFalse: boolean = false;
// Attempting invalid assignment (results in a compile-time error):
// isTrue = 'false'; // Error: Type 'string' is not assignable to type 'boolean'
Special Types: ANY
As a way to get around TypeScript’s strict type system, the any type is a special type. It is regarded as the most superior form of all.
- Flexibility:
anycan be used with any type in the system. A variable typed asanycan be assigned to anything, and a variable typed asanycan be assigned to anything else. - Lack of Type Checking: Expressions containing values that are typed as
anyare not type checked, which is crucial. In essence, you are instructing the compiler to cease analysing that particular value statically. - Warning: Using
anyis equivalent to “opting out of type checking for a variable”. Although useful when porting existing JavaScript code initially, it should be avoided whenever possible, as it makes you “fly blind”. The safer alternative toanyis oftenunknown.
// The 'any' type
let power: any; // Type 'any' used to bypass type checking
power = '123'; // Takes string
power = 123; // Takes number
power = true; // Takes boolean
let num: number;
num = power; // 'any' is compatible with 'number'
// The compiler won't complain even if this causes a runtime error,
// because 'power' is 'any'.
console.log(power.toPrecision(3)); // Output based on JS runtime behavior (e.g., '123.000' if 'power' is 123)
NULL vs. UNDEFINED
TypeScript represents null and undefined, two JavaScript literals, as distinct special types. Both indicate that there is no value.
| Value | Meaning (Convention) |
undefined | Something hasn’t been initialised or a variable has been declared but not assigned a value. |
null | Something is currently unavailable, or an explicit empty value assigned to clear a variable. |
By default (without strictNullChecks), these values are subtypes of all other types, meaning they can typically be assigned to any other type. However, enabling strictNullChecks forces you to explicitly include null or undefined in a type using a union type (e.g., string | null or number | undefined), eliminating the potential runtime issue known as the “billion dollar mistake”.
Checking for Both NULL and UNDEFINED
In practice, when checking for the absence of a value, you often do not need to distinguish between null and undefined. The loose equality check (==) against null or undefined works for both, but using != null is recommended to check if a value is definitely present, as it rules out both null and undefined simultaneously.
// Comparison behavior (using loose equality ==):
console.log(undefined == undefined); // Output: true
console.log(null == undefined); // Output: true
// Checking for the presence of a value using `!= null`
function processArg(arg: string | null | undefined) {
if (arg != null) {
// Here, 'arg' is strictly guaranteed to be a 'string',
// because `!= null` rules out both null and undefined.
console.log(`Processing string: ${arg.toUpperCase()}`);
return;
}
console.log("Argument is absent.");
}
processArg("test string");
// Output: Processing string: TEST STRING
processArg(null);
// Output: Argument is absent.
processArg(undefined);
// Output: Argument is absent.
Special Type: VOID
When a function lacks a return type, it is indicated by the void type. Although void functions are unable to explicitly return any other value, they always automatically return undefined. The return type of a function is void if it lacks an explicit return statement.
The only possible values for the void type itself are null or undefined.
// The 'void' type annotation for a function that doesn't return
function logMessage(message: string): void {
console.log(message);
// Implicitly returns undefined
}
logMessage("Function called successfully.");
// Output: Function called successfully.
// Example of an invalid return (results in a compile-time error):
/*
function invalidReturn(): void {
return "I shouldn't return a value"; // Error: Type 'string' is not assignable to type 'void'.
}
*/
