TypeScript Interfaces

A TypeScript interface describes the required structure of an object. It can specify property names, property types, method signatures, call signatures, and index signatures. TypeScript checks that a value assigned to the interface has the required members with compatible types.

Interfaces support TypeScript’s structural type system. A value does not need to explicitly declare that it uses an interface; it only needs to have the required structure. Interfaces are used during type checking and are removed when TypeScript is compiled to JavaScript.

TypeScript Interface Syntax

Following is the syntax to declare and define an interface :

</>
Copy
 interface interface_name {
     // variables' declaration
     // methods' declaration
 }
  • interface is the keyword used to declare a TypeScript interface.
  • interface_name is the name through which the interface is referenced.
  • The interface body describes the properties and methods that compatible values must provide.
  • An interface describes types; it does not initialize properties or provide runtime behavior.

Creating an Object with a TypeScript Interface

The following interface named Student declares two properties, name and rollnumber, and a function property named displayInformation.

example.ts

</>
Copy
interface Student{
    // variables
    name:string
    rollnumber:number

    // functions
    displayInformation: () => void
}

var student1: Student = {
    name:"Rohit",
    rollnumber:2, 
    displayInformation: ():void => {
        console.log("\n---- Student Information ----")
        console.log("Name is : " + student1.name)
        console.log("Roll Number is : " + student1.rollnumber)
    }
}

console.log(student1.name)
console.log(student1.rollnumber)
student1.displayInformation()

Output

Rohit
2

---- Student Information ----
Name is : Rohit
Roll Number is : 2

JavaScript file when the above .ts while is compiled using tsc :

example.js

</>
Copy
var student1 = {
    name: "Rohit",
    rollnumber: 2,
    displayInformation: function () {
        console.log("\n---- Student Information ----");
        console.log("Name is : " + student1.name);
        console.log("Roll Number is : " + student1.rollnumber);
    }
};
console.log(student1.name);
console.log(student1.rollnumber);
student1.displayInformation();

The object supplies every required member of Student. If a required property is missing or has an incompatible type, the TypeScript compiler reports an error. The generated JavaScript contains the object but not the interface because interfaces have no runtime representation.

Required, Optional, and Readonly Interface Properties

Properties are required by default. Add ? to make a property optional, or add readonly to prevent assignments to that property through the interface after initialization.

</>
Copy
interface UserProfile {
    readonly id: number;
    name: string;
    phoneNumber?: string;
}

const user: UserProfile = {
    id: 101,
    name: "Meera"
};

user.name = "Meera Rao"; // Allowed
// user.id = 102;        // Error: id is readonly

An optional property may be absent, so code should check it before using operations that require a definite value. The readonly modifier is a compile-time restriction; it does not automatically freeze the JavaScript object at runtime.

Declaring Methods in a TypeScript Interface

A method can be written using method syntax or as a property whose type is a function. Both forms describe callable members, although their behavior can differ under advanced type-checking rules.

</>
Copy
interface Calculator {
    add(a: number, b: number): number;
    subtract: (a: number, b: number) => number;
}

const calculator: Calculator = {
    add(a, b) {
        return a + b;
    },
    subtract: (a, b) => a - b
};

console.log(calculator.add(8, 4));
console.log(calculator.subtract(8, 4));
12
4

Extending TypeScript Interfaces

An interface can extend another interface. The derived interface includes the parent members and can add its own requirements. This is useful when several object shapes share a common set of fields.

</>
Copy
interface Person {
    name: string;
    email: string;
}

interface Employee extends Person {
    employeeId: number;
    department: string;
}

const employee: Employee = {
    name: "Anita",
    email: "anita@example.com",
    employeeId: 501,
    department: "Finance"
};

An interface may also extend multiple interfaces by separating their names with commas. If inherited members use the same property name, their types must be compatible.

Implementing a TypeScript Interface in a Class

A class can use the implements clause to have its instance side checked against an interface. The class must provide all required properties and methods, but it may define additional members.

</>
Copy
interface Printable {
    title: string;
    print(): void;
}

class Report implements Printable {
    constructor(public title: string) {}

    print(): void {
        console.log(`Printing: ${this.title}`);
    }
}

const report = new Report("Monthly Sales");
report.print();

The implements clause checks the class; it does not copy method implementations into it. It also does not change how the class or its methods behave in the generated JavaScript.

Function and Index Signatures in TypeScript Interfaces

Interfaces are not limited to ordinary object properties. A call signature describes a callable value, while an index signature describes values accessed using keys whose names are not known in advance.

</>
Copy
interface NumberFormatter {
    (value: number, decimals: number): string;
}

const formatNumber: NumberFormatter = (value, decimals) =>
    value.toFixed(decimals);

interface ScoreMap {
    [playerName: string]: number;
}

const scores: ScoreMap = {
    Asha: 92,
    Vikram: 87
};

With the string index signature in ScoreMap, every property accessed by a string key must have a numeric value.

TypeScript Interface Declaration Merging

Multiple interface declarations with the same name in the same scope are merged. The resulting interface contains members from each compatible declaration.

</>
Copy
interface Settings {
    theme: string;
}

interface Settings {
    notificationsEnabled: boolean;
}

const settings: Settings = {
    theme: "dark",
    notificationsEnabled: true
};

Declaration merging is sometimes used to augment library types. Duplicate properties must use compatible declarations; conflicting property types produce a compiler error.

TypeScript Interface vs Type Alias

Interfaces and type aliases can both describe object shapes, and either is suitable for many application models. Their capabilities are not identical.

CapabilityInterfaceType alias
Describe an object shapeYesYes
Extend an object shapeUses extendsCommonly uses intersections such as &
Declaration mergingSupportedNot supported
Represent primitives, unions, or tuples directlyNoYes
Be implemented by a classYes, for a compatible object shapeYes, when the alias represents a compatible object shape

An interface is often a clear choice for an extensible object or class contract. A type alias is required when the type must directly express a union, primitive alias, conditional type, mapped type, or tuple. Consistency within a codebase is usually more useful than replacing one with the other when both work.

TypeScript Interface vs Class Inheritance

An interface defines a type requirement, whereas class inheritance reuses or specializes an implementation. They solve related but different design problems.

TypeScript interfaceClass inheritance
Describes the members a compatible value must expose.An existing class provides fields, methods, or accessors to a subclass.
Does not contain runtime state or method implementation.Can provide initialized state and implemented behavior.
A class may implement multiple interfaces.A class can extend only one base class.
Removed from emitted JavaScript.Produces JavaScript classes and prototype relationships.
Compatible values may contain additional members.A subclass can add or override members subject to TypeScript’s rules.

Use an interface when different values or classes should expose a common shape without sharing implementation. Use inheritance when a subclass should reuse and specialize behavior from a base class.

Default Values for TypeScript Interface Properties

An interface cannot assign a default property value because it is only a type declaration. Set defaults while creating an object, in a class constructor, or in a factory function.

</>
Copy
interface ConnectionOptions {
    host: string;
    port?: number;
    secure?: boolean;
}

function createConnectionOptions(
    options: ConnectionOptions
): Required<ConnectionOptions> {
    return {
        host: options.host,
        port: options.port ?? 8080,
        secure: options.secure ?? false
    };
}

const options = createConnectionOptions({ host: "localhost" });

The interface marks properties as optional, and the factory supplies their defaults. The nullish coalescing operator preserves valid values such as 0 and false.

Excess Property Checks and Structural Typing

TypeScript generally accepts a value when it contains at least the required interface members. However, a fresh object literal assigned directly to an interface receives an excess property check, which helps detect misspelled or unexpected fields.

</>
Copy
interface Point {
    x: number;
    y: number;
}

const point: Point = {
    x: 10,
    y: 20
    // z: 30 // Error: z is not declared in Point
};

const threeDimensionalPoint = { x: 10, y: 20, z: 30 };
const compatiblePoint: Point = threeDimensionalPoint;

The second assignment is valid because the variable has all members required by Point. This illustrates structural compatibility; it should not be used to bypass an error when an object literal contains a genuine spelling or modeling mistake.

TypeScript Interface Review Checklist

  • Confirm that required properties are truly required and mark only genuinely absent fields with ?.
  • Use readonly for identifiers or references that consumers should not reassign through the interface.
  • Check that method parameter types and return types represent the intended contract.
  • Use extends only when the derived interface is compatible with the parent interface.
  • Remember that interfaces do not validate API responses or other untrusted data at runtime.
  • Choose an index signature only when property names are dynamic and all indexed values follow the declared type.
  • Provide defaults in executable code rather than attempting to place values in an interface.

Frequently Asked Questions About TypeScript Interfaces

What is the purpose of an interface in TypeScript?

An interface gives a name to a required object structure. It helps TypeScript check objects, function parameters, return values, and class instances while allowing different implementations to satisfy the same contract.

Does a TypeScript interface exist at runtime?

No. Interfaces are erased during compilation and do not perform runtime validation. Data received from JSON, an API, or user input requires separate runtime checking before it can be trusted.

Can a TypeScript interface contain default values?

No. An interface can declare required or optional properties but cannot initialize them. Defaults belong in an object initializer, class constructor, or factory function.

Can a class implement more than one TypeScript interface?

Yes. A class can list multiple interfaces after implements, separated by commas. Its instance members must satisfy the combined requirements of those interfaces.

Should I use a TypeScript interface or type alias?

Use either for an ordinary object shape when both fit the project. Interfaces support declaration merging and provide direct extension syntax. Type aliases can additionally represent unions, primitives, tuples, mapped types, and other type expressions.

Summary of TypeScript Interfaces

A TypeScript interface describes the properties and methods expected from a value without supplying their runtime implementation. Interfaces support optional and readonly properties, methods, extension, call signatures, index signatures, declaration merging, and class contracts. In this TypeScript Tutorial, we have used interfaces with object literals and classes and compared them with type aliases and class inheritance.