mgechev / angular-seed

🌱 [Deprecated] Extensible, reliable, modular, PWA ready starter project for Angular (2 and beyond) with statically typed build and AoT compilation
https://mgechev.github.io/angular-seed
MIT License
4.57k stars 1.45k forks source link

Question: TypeScript + external packages (JSPM/npm?) #281

Closed juristr closed 8 years ago

juristr commented 8 years ago

Hi,

I just started playing around with this starter. In doing so, I tried to create a new component that uses Moment.js as an external dependency. I installed it over npm, linked it, also used tsd to add the typings (which got saved in tsd.json). However, Typescript complains it cannot find the module, the application runs without issues.

image

The application just runs fine. On the other side, if I change the moment import like this image ...TypeScript stops complaining, but obviously also the app stops working.

I was also wondering how I could use jspm for installing my dependencies as that one usually wants to have a config.js somewhere. Is that currently a manual process? I found the tools/config.ts file, which I suppose should be the usual config.js one has with System and JSPM, right?

Thx for any insights into this. I'm new to TypeScript as well as JSPM+SystemJS, so... :smile: (the source is here: https://github.com/juristr/angular2-seed/tree/simple-component)

ludohenin commented 8 years ago

@juristr You are probably missing moment definition file. try tsd install moment.

ludohenin commented 8 years ago

The seed does not use JSPM

juristr commented 8 years ago

@ludohenin No, I did: https://github.com/juristr/angular2-seed/blob/simple-component/tsd.json#L47

Used the command you mentioned and apparently it also placed the definition files here: image

but still..

image

(and also in VSCode)

Not sure that's the right place.

juristr commented 8 years ago

@ludohenin Any idea why it doesn't leverage JSPM?

ludohenin commented 8 years ago

Ah I see, Some definition file do not support (the way they are written) the import syntax. My best guess is that this one has be written to use as a Global. using global moment in your code should not bother your IDE. if such is the case you need to either use the global function or make your own .d.ts file to support import syntax OR if you declare import ... 'moment' then you need to set the correct path so Systemjs can load the file.

NathanWalker commented 8 years ago

@juristr You may also look at https://github.com/urish/angular2-moment , it looks like you may have when attempting to import moment_.

// under systemjs, moment is actually exported as the default export, so we account for that
const moment:moment.MomentStatic = (<any>moment_)['default'] || moment_;
juristr commented 8 years ago

@NathanWalker ya I did. In fact otherwise I couldn't even make it to run. Currently my issue is more to get TypeScript recognize the module. The code itself runs properly.

Bigous commented 8 years ago

I think that the problem is with moment.d.ts, not with jspm nor typescript... It seems that it should have a namespace called moment before the definition an it doesn't. Looking at moment itself in tsd, it depends on moment-node... so you should install like this

tsd query moment --action install --resolve --save

but it won't resolve your problem, because the .d.ts exports the MomentStatic and not the module... You could use the import for legacy modules and see what happens...

import moment = require('moment');

As it exports an attribution, I think it should work.

juristr commented 8 years ago

@Bigous Hmm...not sure.

Anyway, I got it to work with these adjustments.

I had already done an installation of moment's TypeScript definition files using tsd install moment --save.

Then in the main file, dateTime.ts, I adjusted it to this:

import { Component } from 'angular2/angular2';
import * as moment from 'moment';

@Component({
    selector: 'date-time',
    template: `
        <span>{{ dateTimeValue }}</span>
    `
})
export class DateTime {
    public dateTimeValue: any;

    constructor() {
        this.dateTimeValue = moment().fromNow();
    }   
}

With these changes, TypeScript recognition and autocomplete started working. The app however broke. to fix that, I had to adjust how moment is registered with System.js in tools/config.ts:

...
export const SYSTEM_CONFIG = {
  defaultJSExtensions: true,
  paths: {
    '*': `${APP_BASE}node_modules/*`,
    'moment': `${APP_BASE}node_modules/moment/moment.js`
  }
};
...

Then everything worked. The src is here.

Note sure whether there's a simpler, nicer way to solve this or whether this is the intended way of importing external libs in this starter? @mgechev ?? Actually I'd like to make use of the placeholder config in config.ts:

...
'*': `${APP_BASE}node_modules/*`,
...

..but with that I couldn't get TypeScript to recognize the moment module.

Bigous commented 8 years ago

Just for curiosity, what is the Typescript version that you are using?

juristr commented 8 years ago

@Bigous Should be the one referenced in the package.json: https://github.com/juristr/angular2-seed/blob/simple-component/package.json#L73

image

ludohenin commented 8 years ago

@juristr if you want to avoid to set SystemJS path and as node_module/moment/moment.js exist (you may have the case with other libs definitions) you can write your own adapter. Like tools/typings/moment_adapter.d.ts

declare module 'moment/moment' {
  export = moment
}

then you can use it in the import statement

import * as moment from 'moment/moment';
juristr commented 8 years ago

:+1: thx for that hint

Bigous commented 8 years ago

Hi @ludohenin I'm trying to do the same with Highcharts at tools/typings/highcharts_adapter.d.ts

/// <reference path="./tsd/highcharts/highcharts.d.ts" />

declare module 'highcharts/js/highcharts.src' {
    export = Highcharts;
}

and importing

import * as HC from 'highcharts/js/highcharts.src';

It gives me the error during watch compile at npm start

app\directives\ng2-highcharts\ng2-highcharts.ts(2,21): error TS2307: Cannot find module 'highcharts/js/highcharts.src'.

but it works... (just the compile error that is annoying me) Do you have any hint? []s

webnugget commented 8 years ago

same issue here with socket.io-client i followed the steps from @juristr and everything is working. the only issue left is that in build.js.dev i get the following error.

[13:50:15] Starting 'build.js.dev'...
app/services/chatService.ts(1,21): error TS2307: Cannot find module 'socket.io-client'.
[13:50:17] TypeScript: 1 semantic error
[13:50:17] TypeScript: emit succeeded (with errors)
[13:50:17] Finished 'build.js.dev' after 1.85 s

do i need to tell gulp-typescript where to find the module?