2
votes

Context: I am trying to create a definition file for a library that I am not the author. When consuming the definition file I created, TypeScript mention it cannot find the definition file.

I have tried several things, here are the last three:

First try (inspired by a similar library d.ts):

declare class MessageFormat {
    constructor(message: string);

    compile: (messageSource: string) => Msg;

}
export type Msg = (params: {}) => string;
export default MessageFormat;

Could not find a declaration file for module 'messageformat'. 'node_modules/messageformat/lib/messageformat.js' implicitly has an 'any' type.

Second try (from TypeScript's example to write d.ts)

declare class MessageFormat {
    constructor(message: string);

    compile: (messageSource: string) => MessageFormat.Msg;

}
declare namespace MessageFormat {
    type Msg = (params: {}) => string;
}
export = MessageFormat;

Could not find a declaration file for module 'messageformat'. 'node_modules/messageformat/lib/messageformat.js' implicitly has an 'any' type.

Third try (from a GitHub question)

declare module "messageformat" {
    export type Msg = (params: {}) => string;
    export interface MessageFormat {
        new(message: string): any;
        compile: (messageSource: string) => Msg;
    }
}

Cannot use 'new' with an expression whose type lacks a call or construct signature.

Code: The three tentatives are in this repo: https://github.com/MrDesjardins/importdefinitionfiles

Can someone give me a pointer about what am I doing wrong?

1
How are you importing the module / trying to invoke new with it?Ryan Cavanaugh
@RyanCavanaugh The third-party module is from npm and imported with import MessageFormat from "messageformat";Patrick Desjardins
Not sure why you suddenly switched to an interface with new(...) method in there in the last example. Changing that to class with a constructor is correct. Also, looking at the source the constructor signature should be: constructor(locale: string|string[]|Object) and the Object should be replaced with a proper interface as well.zenmumbler
Also, no need for export keywords in normal type definitions inside ambient module declarations. Everything is exported & declared by default.zenmumbler
The one export you do need at the end, since MessageFormat is the default export in this module is export = MessageFormat;zenmumbler

1 Answers

1
votes

This works for me, inside some d.ts file in your project, filename is not relevant. DO make sure "messageformat" is the actual name of the node module, otherwise your packager will fail.

declare module "messageformat" {
    type Msg = (params: {}) => string;
    class MessageFormat {
        constructor(locale: string | string[] | Object);
        compile(messageSource: string): Msg;
    }
    export = MessageFormat;
}

Now, in some other module:

import MessageFormat from "messageformat";
const mf = new MessageFormat("en");
const thing = mf.compile("blarb");