Skip to content

TypeScript

TypeScript is a strongly typed programming language that builds on JavaScript.

Installation

shell
# using npm
npm install -g typescript

# using yarn
yarn global add typescript

Types

Basic Types

NOTE

A primitive (primitive value, primitive data type) is data that is not an object and has no methods or properties.

ts
// Basic types (corresponding to JavaScript's primitives)
let message: string = "Hello, world";
let someValue: number = 42;
let isAwesome: boolean = true;

// You can omit type annotations, TypeScript tries to automatically infer the types.
let message = "Hello, world";

any

TypeScript also has a special type, any, that you can use whenever you don’t want a particular value to cause typechecking errors.

ts
let obj: any = { x: 0 };
// None of the following lines of code will throw compiler errors.
// Using `any` disables all further type checking, and it is assumed
// you know the environment better than TypeScript.
obj.foo();
obj.bar = 100;
obj = "hello";
const n: string = obj;

When you don’t specify a type, and TypeScript can’t infer it from context (common in function parameters), the compiler will typically default to any. If you want to avoid this behavior, you can set noImplicitAny flag.

Type Assertion

In TypeScript, Type Assertion is a way to override TypeScript’s type inference, without changing the runtime behavior.

ts
let value: any = "hello";

// Angle Bracket syntax (not allowed in .tsx files)
let length = (<string>value).length;

// `as` syntax (preferred, especially in React/JSX)
let length = (value as string).length;

Arrays

ts
// Typed Arrays (Using Type Annotations)
let ids: number[] = [1, 2, 3]

// Same as above, but Generic Arrays (Using Array<T>)
// Generics are useful when creating complex types.
let ids: Array<number> = [1, 2, 3]

ReadonlyArray

The ReadonlyArray is a special type that describes arrays that shouldn’t be changed (Immutable Arrays).

ts
const colorROArray: readonly string[] = ["red", "green", "blue"];
// Or using Generics
const colorROArray: ReadonlyArray<string> = ["red", "green", "blue"];

Tuples

A tuple type is another sort of Array type that knows exactly how many elements it contains, and exactly which types it contains at specific positions.

ts
let person: [number, string, boolean] = [1, 'Pirate Dev', true]

// Following throw compile errors
let d = person[3] // Tuple type '[number, string, boolean]' of length '3' has no element at index '3'

readonly Tuple Type

Just like arrays, Tuples also have readonly variant.

ts
let person: readonly [number, string, boolean] = [1, 'Pirate Dev', true]

// Following throw compile errors
person[2] = false; // Error: Cannot assign to '2' because it is a read-only tuple
person.push(43); // Property 'push' does not exist on type 'readonly [number, string, boolean]'

Union

ts
let pid: string | number;

// Both the following are acceptable
pid = 23;
pid = '23';

Enums

An enum (short for enumeration) is a special data type that lets you define a set of named constants.

ts
enum Direction {
  North,  // 0
  East,   // 1
  South,  // 2
  West    // 3
}

const move = Direction.North;  // move = 0

Custom values

You can assign custom values to the enum values.

ts
enum Direction {
  North = 2,  // 2
  East,   // 3
  South,  // 4
  West    // 5
}

const move = Direction.South;  // move = 4

String Enum

You can even assign string values in enum.

ts
enum LogLevel {
  Info = "INFO",
  Warning = "WARNING",
  Error = "ERROR"
}

const log = LogLevel.Error;  // log = "ERROR"

// The following line will throw an error for string enum, this works only with numeric enum.
console.log(LogLevel[0]);

Objects

ts
const user: {
  id: number,
  name: string,
  age?: number // Optional property
} = {
  id: 1,
  name: 'Pirate Dev'
}

You can isolate the type as follows:

ts
type User = {
  id: number,
  name: string,
  age?: number // Optional property
}

const user: User = {
  id: 1,
  name: 'Pirate Dev'
}

While type can be used to define the shape of any type (object, union, primitive), there is also interface that can define the shape of an object.

ts
interface User {
  id: number,
  readonly name: string, // Readonly Property
  age?: number // Optional property
}

const user: User = {
  id: 1,
  name: 'Pirate Dev'
}

NOTE

Union and Tuple types are supported only with type, but not interface.

Functions

Return Type

Just like any variable, you can assign a type to the function return value:

ts
function addNumbers(a: number, b: number): number {
  return a + b;
}

Functions need not have a return value, and for such functions, use void as return type.

ts
function logName(name: string): void {
  console.log(name);
}

Interface for Functions

ts
interface Greet {
  (name: string): string;
}

const sayHello: Greet = (name) => {
  return `Hello, ${name}`;
};

Arrow Functions

ts
// "Fat arrow" syntax
const square = (n: number): number => {
  return n * n;
};

// "Fat arrow" syntax with return type inferred
const square = (n: number) => {
  return n * n;
};

// "Fat arrow" syntax with return type inferred, and no return keyword (braceless).
const square = (n: number) => n * n;

Generics in Functions

NOTE

Generics are a way to write flexible and reusable code by allowing types to be passed as parameters. Think of generics as placeholders for types - like variables for types.

ts
// `T` is a generic type parameter
function identity<T>(value: T): T {
  return value;
}

const num = identity<number>(42);     // T is number
const str = identity<string>("hello"); // T is string

Classes

ts
class User {
  // Properties
  id: number;
  name: string;
  age?: number; // Optional property

  // Constructor - called during object instantiation
  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  // Methods
  register() {
    return `${this.name} is now registered`;
  }

  // Static members (properties or methods that belong to the class itself, not to instances of the class)
  static count: number = 0;
}

Interface for Classes

ts
interface IUser {
  id: number;
  name: string;
  age?: number;
  register(): string;
}

class User implements IUser {
  // Properties
  id: number;
  name: string;
  age?: number; // Optional property

  // Constructor - called during object instantiation
  constructor(id: number, name: string) {
    this.id = id;
    this.name = name;
  }

  // Methods
  register() {
    return `${this.name} is now registered`;
  }

  // Static members (properties or methods that belong to the class itself, not to instances of the class)
  static count: number = 0;
}

Access Modifiers

By default, all attributes of a class are Public by default. This can be changed to Private or Protected as well.

  • Public: Accessible anywhere (default behavior).
  • Private: Accessible only within the class that defines it.
  • Protected: Accessible within the class and its sub-classes.

Parameter Property Shorthand

TypeScript has a feature called parameter property shorthand, that saves boilerplate. It does two things:

  • Declares the properties (Ex: id: number)
  • Automatically assigns the constructor parameter value to corresponding property (Ex: this.id = id)

The User class above can be re-written as follows:

ts
class User {
  // Optional property declared separately
  age?: number;

  // Static member
  static count: number = 0;

  // Constructor with PPS for id and name
  constructor(public id: number, public name: string) {
    // `id` and `name` are automatically assigned to this
  }

  register(): string {
    return `${this.name} is now registered`;
  }
}

Inheritance (Extend Classes)

ts
// Base Class: User
class User {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  greet() {
    return `Hello, ${this.name}`;
  }
}

// Subclass: Admin extends User
class Admin extends User {
  role: string;

  constructor(name: string, role: string) {
    super(name); // Call base class constructor
    this.role = role;
  }

  getRole() {
    return `${this.name} is an ${this.role}`;
  }
}

Generics in Classes

ts
class Box<T> {
  constructor(public value: T) {}

  getValue(): T {
    return this.value;
  }
}

const stringBox = new Box<string>("hello");
const numberBox = new Box<number>(123);

tsc command line

The tsc command transpiles TypeScript (.ts) files into JavaScript. It can be used with or without a tsconfig.json file and supports many flags for customizing the compilation process.

Commonly used tsc commands:

CommandDescription
tscTranspiles TypeScript files using tsconfig.json (if present).
tsc file.tsTranspiles a single .ts file into .js.
tsc --watch or tsc -wWatches files for changes and transpiles automatically.
tsc --initCreates a tsconfig.json with default settings.
tsc --outDir ./distOutputs transpiled .js files into the specified directory.
tsc --rootDir ./srcSpecifies the root folder for source files.
tsc --target ES2020Sets the ECMAScript target version (e.g., ES5, ES2020).
tsc --module commonjsSets the module system (commonjs, esnext, etc.).
tsc --strictEnables all strict type-checking options.
tsc --noEmitPerforms type checking without generating any .js output.

tsconfig.json

tsconfig.json is a configuration file used by the TypeScript compiler to understand how to transpile your code. Below are some of the most commonly used options grouped by category:

Core Options

OptionDescriptionExample
targetJavaScript version to output"ES2020"
moduleModule system to use (commonjs, esnext, etc.)"commonjs"
libInclude built-in libraries["ES2020", "DOM"]
allowJsAllow JavaScript files to be compiledtrue
checkJsEnable type-checking for JS filestrue
outDirOutput directory for .js files"dist"
rootDirRoot directory of input .ts files"src"

Strictness Options

OptionDescriptionExample
strictEnable all strict type-checking optionstrue
noImplicitAnyDisallow variables with any type unless explicitly typedtrue
strictNullChecksDisallow assigning null/undefined to other typestrue
strictFunctionTypesEnforce function parameter type compatibilitytrue

Code Quality & Behavior

OptionDescriptionExample
noUnusedLocalsWarn about unused variablestrue
noUnusedParametersWarn about unused function parameterstrue
noEmitOnErrorDon't emit .js if there are type errorstrue
esModuleInteropEnable default import compatibility with CommonJS modulestrue
resolveJsonModuleAllow importing .json filestrue
skipLibCheckSkip type checking of declaration files (.d.ts)true

References & Resources