vasa_c
vasa_c

Reputation: 1014

TypeScript: import external module from node_modules

There is a npm module one-two-three for example. It contains TS files index.ts (the main) and functions.ts.

functions.ts:

export interface IPoint {
    x: number;
    y: number;
}

export function sum(a: IPoint, b: IPoint): IPoint {
    return {
        x: a.x + b.x,
        y: a.y + b.y
    };
}

index.ts:

import functions = require("./functions");

export var sum: typeof functions.sum = functions.sum;

compile:

tsc --module commonjs --declaration index.ts

Files are created: index.js, index.d.ts, functions.js and functions.d.ts. Ok.

There is another library that dependent on one-two-three.

npm install --save one-two-three

I want to include dependence and use it and the interface from functions.ts.

import mo = require("one-two-three");

Error Cannot find external module 'one-two-three'.

/// <reference path="node_modules/one-two-three/index.d.ts" />
import mo = require("one-two-three");

No reaction.

import mo = require("./node_modules/one-two-three");

Fail.

declare var require;

var mo = require("one-two-three");    

It compiles successfully. But there is no type checking. Can write: mo.unknownFunction() and it will be compiled. Can not use interfaces.

How to make the above-described in the correct?

UPDATE

I have achieved the desired behavior follows. Edit d.ts files.

functions.d.ts:

declare module "one-two-three.functions" {
    export interface IPoint {
        x: number;
        y: number;
    }
    export function sum(a: IPoint, b: IPoint): IPoint;
}

index.d.ts:

/// <reference path="./functions.d.ts" />

declare module "one-two-three" {
    import functions = require("one-two-three.functions");
    export var sum: typeof functions.sum;
}

Using it:

/// <reference path="node_modules/one-two-three/index.d.ts" />
/// <reference path="node_modules/one-two-three/functions.d.ts" />

import oneTwoThree = require("one-two-three");
import functions = require("one-two-three.functions");
import IPoint = functions.IPoint;

function delta(a: IPoint, b: IPoint): number {
    var dx: number = a.x - b.x,
        dy: number = a.y - b.y;
    return Math.sqrt(dx * dx + dy * dy);
}

var point1: IPoint = {x: 10, y: 20},
    point2: IPoint = {x: 5, y: 5};

console.log(oneTwoThree.sum(point1, point2));
console.log(delta(point1, point2));

Success. But we have to do double duty. Write code and separately describe the interface.

Is there a way to generate the correct d.ts? The problem is that the d.ts should describe the module with internal syntax (module {}). But source file is CommonJS module. It does not have the section module.

Upvotes: 7

Views: 32861

Answers (1)

Paleo
Paleo

Reputation: 23772

/// <reference path="node_modules/one-two-three/index.d.ts" />
import mo = require("one-two-three");

No reaction.

It should work.

A file .d.ts in TypeScript is like a file .h in C. It's normal to use it when a dependency is imported from another project or sub-project.

If the file your-project/node_modules/one-two-three/index.d.ts isn't written correctly, I suggest to copy it to your-project/one-two-three.d.ts, and then fix the copy. Using the module name as file name makes the /// <reference optional. Just write:

import mo = require("one-two-three");

Upvotes: 6

Related Questions