In my TypeScript code I am using a third-party library called bunyan like so:
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
Because TypeScript cannot resolve the variable bunyan
, I do this to make the TypeScript compiler work:
import * as bunyan from "bunyan";
Unfortunately this causes the following JavaScript output:
var bunyan = require("bunyan");
The require
statement will not work in the browser (when not using a requirejs implementation), so I will receive: Uncaught ReferenceError: require is not defined
.
Actually I don't need the require
statement in my compiled JavaScript because there is a bunyan.min.js
(browserified version) which I can use for the browser. But how can I avoid the bunyan import in my TypeScript code without having the TypeScript compiler complaining about an unknown reference?
I am using TypeScript 1.8 and this is my TypeScript compiler configuration:
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": false,
"removeComments": true,
"target": "es5"
},
"exclude": [
"node_modules",
"typings/browser",
"typings/browser.d.ts"
]
}
You should use declare
to declare a module for bunyan
with Logger
and createLogger
.
declare module bunyan {
export interface Logger {
info(message: string): any;
warn(message: string): any;
}
export function createLogger(options: any): Logger;
};
class MyClass {
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
}
I would recommend using a typings declaration file like the one found here so you get the full benefit of TypeScript :)
I found out that there are two things that come into play:
- Package reference
- Type declaration
Explanation
In my initial code I imported bunyan
which helped the TypeScript compiler to find bunyan's declaration. With the assignment of private logger: bunyan.Logger
I also forced type safety on my logger
variable.
To get rid off the bunyan reference (to also get rid off the compiled var bunyan = require("bunyan");
code) I needed to trick the compiler.
The TS compiler can be cheated by removing the import
and telling TypeScript that there is something (any
) out in the wild which is named bunyan
. This can be done by writing:
declare var bunyan: any;
Because the TS compiler is tricked there is no way for it to guarantee type safety anymore, so the specific type from the logger
variable needs to be removed and it's declaration must look like the following statement:
private logger: any = bunyan.createLogger({name: "MyClass"});
This bring us to the following solution:
Before
// Package reference
import * as bunyan from "bunyan";
// Type declaration
private logger: bunyan.Logger = bunyan.createLogger({name: "MyClass"});
After
// Package reference
declare var bunyan: any;
// Type declaration
private logger: any = bunyan.createLogger({name: "MyClass"});
Thanks James Monger for making this clear to me.