Short note on Typescript Declaration Files

WHAT ARE TYPESCRIPT DECLARATION FILES? A SHORT NOTE ON `.D.TS` FILES. TEACH YOURSELF ON HOW TO WRITE HIGH QUALITY TYPESCRIPT DECLARATION FILES. ADVANTAGES OF TYPESCRIPT DECLARATION FILE.


What are Declaration Files?

Typescript is a superset of Javascript. It adds types and other features which helps in implementing standard programming practices. It’s definitely a very good addon and helps in wonderful and quick programming. But there is a catch.

Javascript is already rich in frameworks and modules that can make any task a breeze to develop. You have a idea in mind and there is 90% chance that its already there and ready to be implemented.

Even though all valid Javascript code is a Typescript code, implementing these frameworks in a Typescript Project doesn’t add any extra value as there are no type definitions and its just as dumb as the other Javascript programs.

Then what is the effective way of reusing a framework of our choice in a Typescript project. Its impossible to rewrite them in Typescript so we can import them in our project. That spoils the fun of code Re-use.

The short answer is Type Definition Files which contain only the type definitions but not the actual code. This helps in enabling the rich features that Typescript offers without rewriting the entire framework.

The compiled Javascript code still references the old framework’s Javascript files and definition files are ignore during run time. This helps only during developmental phase and to spot errors during compile time as is Typescript.


Writing Definition Files

Consider the simple Javascript module

// module.js
export function sum(a, b) {
    return a + b;
}

export function subtract(a, b) {
    return a - b
}

export function multiple(a, b) {
    return a * b
}

export function divide(a, b) {
    return a / b
}

It simply exports math function. This module can be imported into Typescript but with little to no use as it simply doesn’t convey much information Typescript. With implicitAny Configuration in tsconfig.json, you simply cannot even import the module as it has a implicit any type.

// index.ts

import {} from './module' // Error Could not find a declaration file for module './module'. 'd:/jsschools/declarationFiles/module.js' implicitly has an 'any' type

We can solve the problem by defining a module definition file. The file name is going to be the same as before but with extension .d.ts.

// module.d.ts
export function sum(a: number, b: number): number;
export function subtract(a: number, b: number): number;
export function multiple(a: number, b: number): number;
export function divide(a: number, b: number): number;
// index.ts
import {sum} from './module' // Now Error is gone and we see rich help from typescript

const c = sum(1, 2)

Obviously we should understand the module first, understand what datatype the Javascript module expects and then bring it as a declaration file.


Using Interfaces to define complex Input and Output

export const  greet = (greet)  => {
	console.log(`Hello ${greet.salutation} ${greet.person}, This is Javascript. I see that you are     ${greet.age}`)
}

The above Javascript Code expects a object to be passed with 3 attributes salutation, person and age.

The declaration code for the above code can be

export function greet (greet: {
    salutation: string,
    person: string,
    age: string
}): void

Note that its perfectly valid to declare a function as mentioned above this greatly clutters the code and what if we need to use the greet data type for other function.

To enable code reuse and ease of code reading we always use interfaces to declare such complex objects.

interface GreetingImpl {
    salutation: string,
    person: string,
    age: string
}

export function greet (greet: GreetingImpl): void

Declaring Classes

Not just functions and methods, even classes can be declared in a declaration file to enable Typescript import.

Lets rewrite our math functions as a class. Class is built into Javascript from ES6 and helps in performing Object Oriented Programming with Javascript

// module.js
export class Math {
    sum(a, b) {
        return a + b;
    }
    
    subtract(a, b) {
        return a - b
    }
    
    multiple(a, b) {
        return a * b
    }
    
    divide(a, b) {
        return a / b
    }
}

The class above can be declared as

// module.d.ts
export class Math {
    sum(a: number, b: number): number;

    subtract(a: number, b: number): number;

    multiple(a: number, b: number): number;

    divide(a: number, b: number): number;
}

Do’s and Dont’s during declaration:

  1. Never use NumberStringBooleanSymbol and Object as types. These refer to primitives that the Javascript uses
export function add(a: Number, b: Number): Number // Wrong way of doing it
export function add(a: number, b: number): number // OK

2. Avoid any as a type at all cases. This doesn’t help much and adds to value to the additional benefits that are offered by Typescript.

export function add(a: number, b: number) {
    return function(c: any) { // Do not use any as a data type. Be sure about your data
        return a + b + c;
    }
}

export function add(a: number, b: number) {
    return function(c: number) { // Do not use any as a data type. Be sure about your data
        return a + b + c;
    }
}

3. Do not write separate code for overloading a method. Always use single method while declaring. Incorporate the login of overloading with Typescript’s flexible types.

4. Use Optional parameters in cases where the overloaded function differs only in terms of the number of arguments


export function greet(greet: string) : string // Do not overload
export function greet() : string // Do not overload
export function greet(greet?: string): string // right way of doing it

Leave a Comment