I want to create a TypeScript library as private npm package which can be used in Node.js (including 6.x) using ES6 with @types support and TypeScript.
The goal of the library is to extend the Request type from express and provide additional properties.
I created a new Node.js project and add this tsconfig.json:
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"sourceMap": true,
"declaration": true,
"outDir": "./dist",
"strict": true,
"types": ["mocha"]
}
}
These are the relevant parts of the package.json:
{
"name": "@myscope/my-lib",
"main": "dist",
"scripts": {
"build": "rm -rf ./dist && ./node_modules/.bin/tsc",
"test": "./node_modules/.bin/mocha test"
},
"private": true,
"dependencies": {
"joi": "11.4.0"
},
"devDependencies": {
"mocha": "^5.2.0",
"express": "^4.16.4",
"@types/express": "^4.16.1",
"@types/joi": "^14.3.0",
"@types/mocha": "^5.2.5",
"typescript": "^3.2.4"
}
}
My folder structure is this:
- dist
- src
- http
- security
- test
I created a new TypeScript file AuthenticatedRequest.ts in src/http:
import {Request} from "express";
import {UserReference} from "../security/UserReference";
export interface AuthenticatedRequest extends Request {
user: UserReference
}
src/security contains a UserReference.ts:
import {Claim} from "./Claim";
export interface UserReference {
claims: Claim[];
}
and a Claim.ts:
import {IClaim} from "./IClaim";
export class Claim implements IClaim {
type: string;
value: string;
constructor(type: string, value: string) {
this.type = type;
this.value = value;
}
}
IClaim.ts looks like this:
export interface IClaim {
type: string,
value: string
}
In test, I created AuthenticatedRequestTests.js (plain ES6, no TypeScript here to validation code completion and usage from ES6):
'use strict';
const assert = require('assert');
const Claim = require("../dist/security/Claim").Claim;
describe('req', () => {
it('should ', done => {
/** @type {AuthenticatedRequest} */
const req = {};
req.user = { claims: [new Claim('tenantId', '123')] };
assert.equal(req.user.claims[ 0 ].type, 'tenantId');
assert.equal(req.user.claims[ 0 ].value, '123');
return done();
});
});
Now I have sevaral questions:
- Is this the expected TypeScript way to solve this?
- Is it possible to just use
require("../dist/security/Claim");instead ofrequire("../dist/security/Claim").Claim;? - Instead of using this
jsdocstatement/** @type {AuthenticatedRequest} */I would like to use/** @type {myLib.http.AuthenticatedRequest} */
I also created a local test project for integration and installed my library via npm link.
But instead of using
const Claim = require("@scope/my-lib/security/Claim").Claim; I have to use
const Claim = require("@scope/my-lib/dist/security/Claim").Claim;
How can I get rid of the dist folder name here?
Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:

src/index.tsand export everything from that file (e.g.export * from './security/Claim'). Then from your JS code just require@scope/my-lib. As forconst Claim = require(...).Claim, use destructuring:const {Claim} = require(...). You canconsole.log(require(...))if you are unsure what is exported.