0

I'm having the same problem as Chris P with his question, and I understand a bit more about why my issue here happened.

I have sendgrid installed via npm and then typings, and my node_modules has a sendgrid dir and my typings has a global/sendgrid dir.

When I use sendgrid (via 'npm install sendgrid' - straight js, not ts) my working code looks like:

var helper = require('sendgrid').mail;
var from_email = new helper.Email('dina@dfberry.io');
var to_email = new helper.Email('berry.dina@gmail.com');
var subject = 'Hello World from the SendGrid Node.js Library!';
var content = new helper.Content('text/plain', 'Hello, Email!');
var mail = new helper.Mail(from_email, subject, to_email, content);

var sg = require('sendgrid')("SG.TJKAFkv..THIS..IS..THE...KEY");
var request = sg.emptyRequest({
  method: 'POST',
  path: '/v3/mail/send',
  body: mail.toJSON(),
});

sg.API(request, function(error, response) {
  console.log(response.statusCode);
  console.log(response.body);
  console.log(response.headers);
});

When I look at the sendgrid/index.d.ts ( via 'typings install dt~sendgrid --global --save'), I see two modules, Sendgrid & 'sendgrid'. Why are there two modules?

//sendgrid/index.d.ts
// Generated by typings
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/ac94ea73311e9d5607f919b5c174d66d72c78a29/sendgrid/sendgrid-1.1.0.d.ts
declare module Sendgrid {
    //#region Options

    export interface UriParts {
        protocol: string;
        host: string;
        port: string;
        endpoint: string;
    }

    export interface Options {
        protocol?: string;
        host?: string;
        port?: string;
        endpoint?: string;
        uri?: string;
        proxy?: string;
        web?: {
            pool?: any;
        }
    }

    export interface OptionsExport {
        uriParts: UriParts;
        uri: string;

        proxy?: string;
        web?: {
            pool?: any;
        }
    }

    //#endregion

    //#region Email

    export interface EmailOptions {
        to?: any;
        toname?: string;
        from?: string;
        fromname?: string;
        subject?: string;
        text?: string;
        html?: string;
        bcc?: any;
        replyto?: string;
        date?: Date;
        headers?: { [key: string]: string };
        files?: FileHandlerOptions[];
        smtpapi?: any;
    }

    export class Email {
        to: any;
        toname: string;
        from: string;
        fromname: string;
        subject: string;
        text: string;
        html: string;
        bcc: any;
        replyto: string;
        date: Date;
        headers: { [key: string]: string };
        files: FileHandler[];
        smtpapi: any;

        constructor();
        constructor(options: EmailOptions);

        addTo(address: string): void;
        addHeader(type: string, value: string): void;
        addSubstitution(type: string, value: string): void;
        addSubstitution(type: string, value: string[]): void;
        addSection(section: { [key: string]: string }): void;
        addUniqueArg(uarg: { [key: string]: string }): void;
        addCategory(category: string): void;
        addFilter(filter: string, command: string, value: number): void;
        addFilter(filter: string, command: string, value: string): void;
        addFile(file: FileHandlerOptions): void;

        setFrom(address: string): void;
        setSubject(subject: string): void;
        setText(text: string): void;
        setHtml(html: string): void;
        setHeaders(headers: { [key: string]: string }): void;
        setSubstitutions(substitutions: { [key: string]: string[] }): void;
        setSections(sections: { [key: string]: string }): void;
        setUniqueArgs(uargs: { [key: string]: string }): void;
        setCategories(categories: string[]): void;
        setFilters(filters: any): void;
    }

    //#endregion

    //#region FileHandler

    export interface FileHandlerOptions {
        filename?: string;
        contentType?: string;
        cid?: string;
        path?: string;
        url?: string;
        content?: any;
    }

    export class FileHandler {
        filename: string;
        contentType: string;
        cid: string;

        type: string;
        content: string;
        path: string;
        url: string;

        constructor(options: FileHandlerOptions);

        loadContent(callback: HandlerCallback): void;

        static handlers: {
            content: Handler;
            path: Handler;
            url: Handler;
            none: Handler;
        };
    }

    export interface Handler {
        (file: FileHandler, callback: HandlerCallback): void;
    }

    export interface HandlerCallback {
        (hasError: boolean, error: Error): void;
        (hasError: boolean, error: string): void;
    }

    //#endregion

    //#region Sendgrid Class

    interface Constructor {
        (api_user: string, api_key: string, options?: Options): Instance;
        new (api_user: string, api_key: string, options?: Options): Instance;
    }

    export interface Instance {
        version: string;
        api_user: string;
        api_key: string;
        options: OptionsExport;
        Email: typeof Email;

        send(email: EmailOptions, callback: (err: Error, json: any) => any): void;
        send(email: Email, callback: (err: Error, json: any) => any): void;
    }

    //#endregion
}

declare module "sendgrid" {
    var ctor: Sendgrid.Constructor;
    export = ctor;
}

The exported stuff that I think I want to use is class Sendgrid.Email and "sendgrid".ctor.

While I realize I can make ts use my js and just be done with it, I want to understand how to use the sendgrid/index.d.ts or if I even should. The file says it is generated from typings so I assume typings ran over the node_modules sendgrid files and decided how to build it out as a d.ts file.

However, when I use ts to bring sendgrid in, it doesn't work how I think it should work.

I think I need to create the Constructor(api_user, api_key, options) and get the returned Instance. Then use the Instance.send() to send the email.

When I use VSCode, the intellisense shows the sendgrid/index.d.ts objects but when I call the compiled to js file, the objects are empty.

How do I read/use the sendgrid/index.d.ts file to write against the sendgrid and have both the intellisense (which works now) and the compiled js file work (which doesn't work now).

As you can read from Chris's SO, the ts code compiles but the very first object that uses the d.ts file is undefined.

Is the d.ts file just wrong? How would I know this is in the future? Other than the intellisense, the d.ts file doesn't connect meaningfully to the underlying sendgrid library.

Community
  • 1
  • 1
DFBerry
  • 1,818
  • 1
  • 19
  • 37
  • I think the d.ts file is either out of sync or not related to the sendgrid I think it should be related to. I'm going to build my own d.ts file from scratch. – DFBerry Sep 05 '16 at 21:32
  • 1
    Possible duplicate of [Typescript definitions for sendgrid](http://stackoverflow.com/questions/36446199/typescript-definitions-for-sendgrid) – Edmar Miyake Jan 21 '17 at 18:13

1 Answers1

1

I see two modules, Sendgrid & 'sendgrid'. Why are there two modules

The Sendgrid defines Sendgrid in the global namespace. This allows other developers to easily add / fix features exported by the definition.

The 'sendgrid' module is pointing to the NPM module that you can import/require. This provides you with safety when you do import Sendgrid = require('sendgrid'). This is the recommended usage (big fan of modules here).

basarat
  • 261,912
  • 58
  • 460
  • 511