How to import external NPM module with Typescript declarations using JSPM

一笑奈何 提交于 2019-12-06 02:57:47

This is a answer I don't like but is a work around. In fact I come across your question while searching for a answer to my case, they are similar.

In my case I create a external library too, that library is compiled with typescript and the module is generated to be consumed in external jspm projects.

What works for me is to import the library with the same syntax of javascript es6. Suppose the library is named myLib and have a config.js map of myLib=blabla and you have a file called notify.js (generated from typescript). The import is

import Notify from 'myLib/notify'

At runtime it works, but the problem is that the compiler for the project cannot locate 'myLib/notify'. The definition generated by typescript (file jspm_package/github/myLib/myLib@version/notify.d.ts for the library is something like:

export declare enum NotifyStatus {
    INFO = 0,
    SUCCESS = 1,
    WARNING = 2,
    DANGER = 3,
}
export declare enum NotifyPosition {
    TOP_CENTER = 0,
    TOP_LEFT = 1,
    TOP_RIGHT = 2,
    BOTTOM_CENTER = 3,
    BOTTOM_LEFT = 4,
    BOTTOM_RIGHT = 5,
}
/**
 * Class for notifications
 */
export declare class Notify {
    /**
     * Show a default Notification in the page
     * @param  {string}            message      The message
     * @param  {NotifyStatus   =            NotifyStatus.INFO} status   Status to style the message
     * @param  {[type]}            timeout=5000 Timeout
     * @param  {NotifyPosition =                                NotifyPosition.TOP_CENTER} pos        Position to display the message
     * @return {NotifyMessage}                  A object representing the message on the DOM
     */
    static show(message: string, status?: NotifyStatus, timeout?: number, pos?: NotifyPosition): NotifyMessage;
    private static getStatusString(status);
    private static getPositionString(position);
}
export interface DialogModal {
    show(): any;
    hide(): any;
}

To work around I manually modify the definition wrapping in a declaration of a library:

declare module 'myLib/notify' {
export declare enum NotifyStatus {
    INFO = 0,
    SUCCESS = 1,
    WARNING = 2,
    DANGER = 3,
}
export declare enum NotifyPosition {
    TOP_CENTER = 0,
    TOP_LEFT = 1,
    TOP_RIGHT = 2,
    BOTTOM_CENTER = 3,
    BOTTOM_LEFT = 4,
    BOTTOM_RIGHT = 5,
}
/**
 * Class for notifications
 */
export declare class Notify {
    /**
     * Show a default Notification in the page
     * @param  {string}            message      The message
     * @param  {NotifyStatus   =            NotifyStatus.INFO} status   Status to style the message
     * @param  {[type]}            timeout=5000 Timeout
     * @param  {NotifyPosition =                                NotifyPosition.TOP_CENTER} pos        Position to display the message
     * @return {NotifyMessage}                  A object representing the message on the DOM
     */
    static show(message: string, status?: NotifyStatus, timeout?: number, pos?: NotifyPosition): NotifyMessage;
    private static getStatusString(status);
    private static getPositionString(position);
}
export interface DialogModal {
    show(): any;
    hide(): any;
}
}

My tsconfig.json file is configured to look in jspm_packages for definitions

And then the compile stops warning and Atom editor provides intellisense.

There are two problems with this approach:

  1. The wraps is made manually (this is annoying)
  2. myLib is handwritten in the definition and can't be changed for other location, we must use import 'myLib/bla' and in reality 'myLib' can be overridden by SystemJS and jspm to other reference.

What I'm searching is a way to auto generate the typescript definition with the module declaration.

I came across this https://www.npmjs.com/package/autodts but I do not fully understand how it works, but it seams that can be use to automatically generate the definition file in this way.

Edit:

I create a gulp task to edit typescript definition files and add automatic add declare module. Here is how:

var gulp = require('gulp');
var runSequence = require('run-sequence');
var ts = require('gulp-typescript');
var paths = require('../paths');
var through2 = require('through2');
var concat = require('gulp-concat');
var insert = require('gulp-insert');
var rename = require('gulp-rename');
var merge = require('merge2');
var modify = require('gulp-modify');

var tsProjectAmd = ts.createProject('tsconfig.json', {module: 'amd'});
var tsProjectES6 = ts.createProject('tsconfig.json', {module: 'es6'});
var tsProjectCOMMONJS = ts.createProject('tsconfig.json', {module: 'commonjs'});
var tsProjectSystem = ts.createProject('tsconfig.json', {module: 'system'});

 var makeBuild = function(project, format, path, output){
  return function(){
    var tsResult =  gulp.src(path)
      .pipe(ts(project));
    return merge([
      tsResult.js.pipe(gulp.dest(output + format)),
      tsResult.dts.pipe(modify({
        fileModifier: function(file, content){
          // Split at /dist/ caracter
          var regex = new RegExp("/" + paths.dist);
          var split = file.path.split(regex);
          // Remove ".d.ts";
          var fileNameAndPath = split[1].slice(0, split[1].length - 5);
          if(fileNameAndPath != paths.packageName){
            return  'declare module "' + paths.packageName + "/" + fileNameAndPath + '" {\n' + content + '\n}';
          }else {
            return content;
          }

        }
      })).pipe(gulp.dest(output + format))
    ]);
  }
}


gulp.task('build-amd', makeBuild(tsProjectAmd, '', paths.source, paths.output));

paths.js

var path = require('path');
var fs = require('fs');

var appRoot = 'src/';
var outputRoot = 'dist/src/';
var pkg = JSON.parse(fs.readFileSync('./package.json', 'utf-8'));

module.exports = {
  root: appRoot,
  source: [appRoot + '**/*.ts','typings/**/*.ts'],
  html: appRoot + '**/*.html',
  style: outputRoot + 'css/**/*.css',
  styles: outputRoot + 'css/',
  less: ['less/theme/**/*.less','!less/theme/_variables.less'],
  fonts: 'less/uikit/src/fonts/*',
  images: 'images/**/*',
  output: outputRoot,
  doc:'./docs',
  apiDoc: './api-doc',
  dist: 'dist/',
  testsFixtures: 'test/fixtures/*',
  specsSrc: 'test/**/*.ts',
  specsOutput: 'dist/',
  packageName: pkg.name
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!