Get ready for your next interview with our comprehensive question library
TypeScript code is compiled using the TypeScript compiler (tsc
):
# Install TypeScript globally
npm install -g typescript
# Compile a single file
tsc app.ts
# Compile with watch mode
tsc app.ts --watch
# Compile using tsconfig.json
tsc
The compiler reads .ts
files and outputs .js
files that can run in any JavaScript environment.
Type inference is TypeScript's ability to automatically determine types without explicit type annotations. The compiler analyzes the code and infers the most appropriate types.
let message = "Hello"; // TypeScript infers string type
let count = 42; // TypeScript infers number type
let isActive = true; // TypeScript infers boolean type
function add(a: number, b: number) {
return a + b; // Return type inferred as number
}
Type annotations are explicit type declarations that tell TypeScript what type a variable, parameter, or return value should be.
// Variable annotations
let username: string = "john";
let age: number = 25;
let isLoggedIn: boolean = false;
// Function parameter and return type annotations
function greet(name: string): string {
return `Hello, ${name}!`;
}
// Array annotations
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob"];
TypeScript supports all JavaScript primitive types plus additional ones:
string
: Text datanumber
: Numeric values (integers and floats)boolean
: True/false valuesnull
: Intentional absence of valueundefined
: Uninitialized valuesymbol
: Unique identifiersbigint
: Large integersvoid
: Absence of return valuenever
: Values that never occurany
: Disables type checkingunknown
: Type-safe alternative to anyAn interface defines the structure of an object, specifying what properties and methods it should have.
interface User {
id: number;
name: string;
email: string;
isActive?: boolean; // Optional property
readonly createdAt: Date; // Read-only property
}
const user: User = {
id: 1,
name: "John Doe",
email: "john@example.com",
createdAt: new Date()
};
Use the extends
keyword to inherit properties from other interfaces:
interface Shape {
color: string;
}
interface Circle extends Shape {
radius: number;
}
interface Rectangle extends Shape {
width: number;
height: number;
}
// Multiple inheritance
interface TimestampedShape extends Shape, Timestamped {
area: number;
}
interface Timestamped {
createdAt: Date;
updatedAt: Date;
}
Optional properties are marked with ?
and may or may not be present in the object:
interface Config {
apiUrl: string;
timeout?: number; // Optional
retries?: number; // Optional
debug?: boolean; // Optional
}
const config: Config = {
apiUrl: "https://api.example.com"
// Other properties can be omitted
};
// Function with optional parameters
function createUser(name: string, age?: number): User {
return {
name,
age: age ?? 18 // Default value if not provided
};
}
Readonly properties can only be assigned during initialization and cannot be modified afterward:
interface Point {
readonly x: number;
readonly y: number;
}
const point: Point = { x: 10, y: 20 };
// point.x = 30; // Error: Cannot assign to 'x' because it is read-only
// Readonly arrays
const readonlyArray: readonly number[] = [1, 2, 3];
// readonlyArray.push(4); // Error: Property 'push' does not exist
// ReadonlyArray type
const numbers: ReadonlyArray<number> = [1, 2, 3];
Classes in TypeScript include type annotations and access modifiers:
class Person {
// Properties
private _id: number;
protected name: string;
public email: string;
constructor(id: number, name: string, email: string) {
this._id = id;
this.name = name;
this.email = email;
}
// Methods
public greet(): string {
return `Hello, I'm ${this.name}`;
}
protected getId(): number {
return this._id;
}
}
TypeScript provides three access modifiers:
public
(default): Accessible everywhereprivate
: Accessible only within the same classprotected
: Accessible within the class and its subclassesclass BankAccount {
public accountNumber: string;
private balance: number;
protected accountType: string;
constructor(accountNumber: string, initialBalance: number) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
this.accountType = "savings";
}
public getBalance(): number {
return this.balance; // Accessing private property within class
}
private calculateInterest(): number {
return this.balance * 0.05;
}
}
class PremiumAccount extends BankAccount {
constructor(accountNumber: string, initialBalance: number) {
super(accountNumber, initialBalance);
// this.balance; // Error: private property
console.log(this.accountType); // OK: protected property
}
}
TypeScript fully supports ES6 module syntax for importing and exporting:
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
export default function multiply(a: number, b: number): number {
return a * b;
}
export const PI = 3.14159;
// app.ts
import multiply, { add, subtract, PI } from './math';
import * as MathUtils from './math';
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
console.log(MathUtils.PI); // 3.14159
NonNullable<T>
removes null and undefined from a type:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>; // string
function processValue(value: string | null | undefined): void {
if (value !== null && value !== undefined) {
// Type narrowing
const processed: NonNullable<typeof value> = value; // string
console.log(processed.toUpperCase());
}
}
// Useful with arrays
type ArrayItem<T> = T extends (infer U)[] ? NonNullable<U> : never;
type StringArrayItem = ArrayItem<(string | null)[]>; // string
TypeScript supports JavaScript's error handling mechanisms with additional type safety:
// Basic try-catch
function parseNumber(value: string): number {
try {
const parsed = parseInt(value);
if (isNaN(parsed)) {
throw new Error(`Invalid number: ${value}`);
}
return parsed;
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
}
throw error;
}
}
// Custom error types
class ValidationError extends Error {
constructor(
message: string,
public field: string,
public value: any
) {
super(message);
this.name = 'ValidationError';
}
}
function validateEmail(email: string): void {
if (!email.includes('@')) {
throw new ValidationError('Invalid email format', 'email', email);
}
}
Upgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumUpgrade to Premium to see the answer
Upgrade to PremiumAccess all premium content - interview questions, and other learning resources
We regularly update our features and content, to ensure you get the most relevant and updated premium content.
1000 monthly credits
Cancel anytime