Search code examples
typescriptbrowserifytsify

Typescript generic function and indexed argument


I have following package.json:

{
    "name": "browserify-test",
    "version": "1.0.0",
    "description": "",
    "main": "dist/index.js",
    "typings": "dist/index.d.ts",
    "scripts": {
        "build:tsc": "tsc --outDir dist",
        "build:browser": "browserify src/index.ts -p tsify --standalone MyLib > dist/myLib.js"
    },
    "devDependencies": {
        "browserify": "^14.0.0",
        "tsify": "^3.0.0",
        "typescript": "^2.1.5"
    }
}

Following tsconfig.json:

{
    "compilerOptions": {
        "noImplicitAny": true,
        "module": "commonjs",
        "target": "ES5",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "sourceMap": true,
        "declaration": true
    }
}

File src/evets.d.ts:

export interface MyEvent {
    name: string
}

And finally entry point src/index.js:

import * as events from './events';

export class MyLibrary {
    public test(eventInstance: events.MyEvent) {
        console.log(eventInstance);
        console.log(events);
    }
}

Building pure typescript version works. So command npm run build:tsc works perfectly but trying to build with browserify, so invoking npm run build:browser i get following error:

> [email protected] build /home/aszmyd/tmp/browserify-test
> browserify src/index.ts -p tsify --standalone MyLib > dist/myLib.js

Error: Cannot find module './events' from '/home/aszmyd/tmp/browserify-test/src'

It seems that browserify cannot properly consume type definition files with d.ts extension.


The above example WORKS in two cases:

  1. When in index.ts i import like this: import * as events from './events.d; (note the ending .d)

  2. When i remove the console.log(events); line (?!) - how it can use events.*** types but cannot use the whole set (alias) ?


I think im missing something dummy here but im lack of ideas.


Solution

  • Running

    import * as events from './events';
    

    attempts to import a typescript file called 'events.ts' located in the same directory as the importing file. That is because it is a relative path.

    (importing ./events.d will import events.d.ts in the same directory, explaining why "it works")

    To import an external module, the import statement is made using the module name (not a path). Hence for a module called 'events', the import statement would be

    import * as events from 'events'
    

    When importing an external module, the compiler will look for a definition file, "typing" the module. Depending on how the module is structured this file could be an internal module definition looking like your 'event.d.ts' or an external module definition file which would more likely look like

    declare module 'events' {
        export interface MyEvent {
            name: string
        }
    }