angular - TypeScript-typdefinition; export default för att använda ett externt JavaScript-bibliotek i Angular2


Jag försöker integrera ett JavaScript-bibliotek (bricks.js) som inte har någon offentligt tillgänglig typedefinition.

I princip är det biblioteket exporterar något som detta:

export default (config) => {

    const instance = SomeConstructorFunction(config);
    return instance;
}

Jag kan inte lista ut hur jag korrekt skapar en typdefinition (.d.ts) för denna funktion; antingen kompilerar tsc när jag importerar, jag får undefined eller så kommer tsc inte att kompilera.

För detta exempel kompilerar .d.ts:

declare module 'bricks.js' {
    export class Bricks {
         constructor(config: any);
         pack(); // some function available on the instance
   }
}

Men om jag importerar så här, inuti min AngularJs 2-komponent:

import { Bricks } from 'bricks.js';
this.bricks = new Bricks({//some config here});

Då är Bricks undefined, vilket därför utlöser ett fel :-).

Jag förstår inte riktigt hur man bygger en .d.ts för det biblioteket; dessutom är biblioteket kompilerat med Babel, och jag misstänker att Babel gör något med standardimporter av arrow-funktioner...

Svar #1

Okej, hittade min väg genom denna lilla mardröm...

Biblioteket bricks.js definieras med ES6-moduler (src-mappen) men byggs också med Babel.

Jag använder Systemjs för att ladda mina Angular2-projektberoenden,

Så i princip har jag två alternativ därifrån:

  • använd ES6 bricks.js från src-mappen. Det innebär att använda den moderna TypeScript-syntaxen för att ladda ES6-moduler och sedan deklarera en transpilator i Systemjs-konfigurationen så att den kan ladda biblioteket och dess beroenden korrekt.

  • eller använd den Babel-transpilerade bricks.min.js från dist-mappen. Jag måste använda icke-modulens syntaks.

Se https://stackoverflow.com/a/29598404/254439

Jag valde den andra lösningen för att undvika transpilation från Systemjs.

Så här är vad jag gjorde:

.index.d.ts

declare module 'bricks.js' {
    interface Bricks {
        pack();
    }

    function bricksFactory(config:any): Bricks

    export = bricksFactory;

}

systemjs.config.js

...
var map = {
    ...
    'bricks.js':                  'node_modules/bricks.js/dist/'
    ...
}
...
var packages = {
    ...
    'bricks.js':                  { main: 'bricks.min.js', defaultExtension: 'js'}
};

min.komponent.ts

import bricksFactory = require('bricks.js');

this.bricksInstance =  Bricks({
    container: '.mycontainer',
    packed: 'data-packed',
    sizes: [
        { columns: 2, gutter: 10 },
        { mq: '768px', columns: 3, gutter: 25 },
        { mq: '1024px', columns: 4, gutter: 50 }
    ]
});

Svar #2

Du kan importera koden med import * as Bricks from 'bricks.js';

Du kan definiera det med något liknande

declare module "Bricks" {
  function loadConfig(config): SomeConstructorFunction;
    var _tmp = loadConfig;
   export = _tmp;
}