TypeScript Unlocked: Interfaces

TypeScript Unlocked: Interfaces

💡
This article is a part of TypeScript Unlocked Series on my blog. Every article in the series is short, crisp and filled with examples and code snippets. If you want to learn TypeScript from scratch for absolutely FREE!!! check it out.

Interfaces works similar to type keyword which we have discussed earlier in the series. Interface allows us to define the structure of the object just like type but there are few differences.

interface User {
    readonly id : number // setting this as readonly field
    name: string 
    age?: number // setting this as optional field
    isLoggedIn(): string // method named isLoggedIn which returns string
    getStatus: () => string // similar methods can also be defined using this syntax
    getName(id:number) : string
}

const user: User = {
    id: 1234321,
    name: "Palash",
    isLoggedIn: ()=>{
        return "YES"
    },
    getStatus: ()=>{
        return "Online"
    },
    getName:(id:2)=>{
        return "usr" + id
    }
}

Reopening of Interface

Sometimes we may want to add some additional properties to our interfaces after they has been defined. For example, if you have imported some library and it has some interfaces which you want to update. You can use the following syntax but this changes the original interface as well so if you are using the original interface in the future you have to add the new property which you have added.

interface User {
    readonly id : number // setting this as readonly field
    name: string 
    age?: number // setting this as optional field
    isLoggedIn(): string // method named isLoggedIn which returns string
    getStatus: () => string // similar methods can also be defined using this syntax
    getName(id:number) : string
}

interface User { // reopening the Interface 
    phone: number
}

const user: User = {
    id: 1234321,
    name: "Palash",
    phone: 9898767852,
    isLoggedIn: ()=>{
        return "YES"
    },
    getStatus: ()=>{
        return "Online"
    },
    getName:(id:2)=>{
        return "usr" + id
    }
}

Inheritance

we just saw how you can reopen an interface and add new properties but the drawback was it changes the original interface as well. So, if you want to update your interface but don't want to change the original one, we can use Inheritance. Inheritance establishes a relation between the parent interface and the child interface and both the interfaces are two separate interfaces. The child interface will have all the properties of the parent interface. One thing to note here is that unlike classes overriding methods of interfaces does not work.

interface User {
    readonly id : number // setting this as readonly field
    name: string 
    age?: number // setting this as optional field
    isLoggedIn(): string // method named isLoggedIn which returns string
    getStatus: () => string // similar methods can also be defined using this syntax
    getName(id:number) : string
}

interface Admin extends User { // extending the Admin interface from user
    role: string
}

const admin: Admin = {
    id: 1234321,
    name: "Palash",
    role: "Admin",
    isLoggedIn: ()=>{
        return "YES"
    },
    getStatus: ()=>{
        return "Online"
    },
    getName:(id:2)=>{
        return "usr" + id
    }
}

}

Interface implements

In TypeScript, the implements keyword is used to enforce that a class must conform to a particular interface or multiple interfaces. When a class implements an interface, it means the class must contain all the members (properties and methods) defined in that interface.

interface MyInterface {
    // Properties or methods defined in the interface
}

class MyClass implements MyInterface {
    // Implementation of the properties or methods defined in the interface
}
interface Printable {
    print(): void;
}

class Document implements Printable {
    print() {
        console.log('Printing document...'); // Implementing the 'print()' method from the 'Printable' interface
    }
}

const document = new Document();
document.print(); // Outputs: Printing document...

Syntax for Implementing Multiple Interfaces:

interface Interface1 {
    method1(): void;
}

interface Interface2 {
    method2(): void;
}

class MyClass implements Interface1, Interface2 {
    method1() {
        // Implementation for method1
    }

    method2() {
        // Implementation for method2
    }
}

Difference between type Aliases and Interface

Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.

TYPE

Extending a type via intersections

type Animal = {
  name: string;
}

type Bear = Animal & { 
  honey: boolean;
}

const bear = getBear();
bear.name;
bear.honey;

A type cannot be changed after being created

type Window = {
  title: string;
}

type Window = {
  ts: TypeScriptAPI;
}

 // Error: Duplicate identifier 'Window'.

INTERFACE

Extending an interface

interface Animal {
  name: string;
}

interface Bear extends Animal {
  honey: boolean;
}

const bear = getBear();
bear.name;
bear.honey;

Adding new fields to an existing interface

interface Window {
  title: string;
}

interface Window {
  ts: TypeScriptAPI;
}

const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});