Skip to content

Question: How to get the types array to load using System.js. #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bennadel opened this issue Oct 24, 2016 · 7 comments
Closed

Question: How to get the types array to load using System.js. #170

bennadel opened this issue Oct 24, 2016 · 7 comments

Comments

@bennadel
Copy link

bennadel commented Oct 24, 2016

I am currently using the plugin-typescript to do in-browser compiling of an Angular 2 application, but I can't seem to get the types to be loaded. Here are the typescript options I have in my system.js config:

typescriptOptions: {
    emitDecoratorMetadata: true,
    experimentalDecorators: true,
    module: "commonjs",
    moduleResolution: "node",
    noImplicitAny: true,
    removeComments: false,
    sourceMap: true,
    suppressImplicitAnyIndexErrors: true,
    target: "es5",
    typeCheck: true,
    types: [ "node" ]  // <---- This is the part I am trying to get to work.
}

... notice the types: [ "node" ]. However, when I load the app, I do not see any network requests to node_modules/@types/node. Is there something that I have to do to tell the typescript plugin to actually load the types?

Because it's not loading, my references to moduleId: module.id are throwing the error:

TypeScript [Error] Cannot find name 'module'. (TS2304)

Everything else is working, in so much as the .ts files are being loading and transpiled to es5 and my Angular 2 app loads. I just can't figure out how to get rid of that compiler error. Thanks!

Also, my dependencies in package.json:

"dependencies": {
    "@angular/common": "2.1.1",
    "@angular/compiler": "2.1.1",
    "@angular/core": "2.1.1",
    "@angular/forms": "2.1.1",
    "@angular/http": "2.1.1",
    "@angular/platform-browser": "2.1.1",
    "@angular/platform-browser-dynamic": "2.1.1",
    "@angular/router": "3.1.1",
    "@types/core-js": "^0.9.34",
    "@types/node": "^6.0.45",
    "core-js": "^2.4.1",
    "plugin-typescript": "5.2.7",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.39",
    "typescript": "^2.0.3",
    "zone.js": "^0.6.25"
}
@bennadel
Copy link
Author

If I use files instead of types, it seems to load the d.ts file; but, I am not sure this is the recommended approach?

typescriptOptions: {
    ....
    files: [ "vendor/node_modules/@types/node/index.d.ts" ],
    ....
}

@aluanhaddad
Copy link
Contributor

What does the rest of your system.config.js file look like?

@bennadel
Copy link
Author

bennadel commented Nov 1, 2016

@aluanhaddad this is what I have at the moment for my in-browser demos:

(function( global ) {

    System.config({
        paths: {
            "vendor/*": "../../vendor/angular2/2.1.1/*",
            "~/*": "./app/*"
        },
        map: {
            "@angular": "vendor/node_modules/@angular",
            "plugin-typescript": "vendor/node_modules/plugin-typescript/lib/plugin.js",
            "rxjs": "vendor/node_modules/rxjs",
            "ts": "vendor/node_modules/plugin-typescript",
            "typescript": "vendor/node_modules/typescript"
        },
        packages: {
            "@angular/common": {
                main: "bundles/common.umd.js",
                meta: {
                    "bundles/common.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/compiler": {
                main: "bundles/compiler.umd.js",
                meta: {
                    "bundles/compiler.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/core": {
                main: "bundles/core.umd.js",
                meta: {
                    "bundles/core.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/forms": {
                main: "bundles/forms.umd.js",
                meta: {
                    "bundles/forms.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/http": {
                main: "bundles/http.umd.js",
                meta: {
                    "bundles/http.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/platform-browser": {
                main: "bundles/platform-browser.umd.js",
                meta: {
                    "bundles/platform-browser.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/platform-browser-dynamic": {
                main: "bundles/platform-browser-dynamic.umd.js",
                meta: {
                    "bundles/platform-browser-dynamic.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "@angular/router": {
                main: "bundles/router.umd.js",
                meta: {
                    "bundles/router.umd.js": {
                        typings: "index.d.ts"
                    }
                }
            },
            "app": { 
                main: "main.ts",
                defaultExtension: "ts",
                meta: {
                    "*.ts": {
                        loader: "ts"
                    }
                }
            },
            "vendor/node_modules": {
                defaultExtension: "js"
            },
            "rxjs": {
                meta: {
                    "*.js": {
                        typings: true
                    }
                }
            },
            "ts": {
                main: "lib/plugin.js"
            },
            "typescript": {
                main: "lib/typescript.js",
                meta: {
                    "lib/typescript.js": {
                        exports: "ts"
                    }
                }
            }
        },
        transpiler: "plugin-typescript",
        transpiler: "ts",
        typescriptOptions: {
            emitDecoratorMetadata: true,
            experimentalDecorators: true,
            files: [ "vendor/node_modules/@types/node/index.d.ts" ],
            module: "commonjs",
            moduleResolution: "node",
            noImplicitAny: true,
            removeComments: false,
            sourceMap: true,
            suppressImplicitAnyIndexErrors: true,
            target: "es5",
            typeCheck: true
        }
    });

    // Load "./app/main.ts" (gets full path from package configuration above).
    global.bootstrapping = System
        .import( "app" )
        .then(
            function handleResolve() {

                console.info( "System.js successfully bootstrapped app." );

            },
            function handleReject( error ) {

                console.warn( "System.js could not bootstrap the app." );
                console.error( error );

                return( Promise.reject( error ) );

            }
        )
    ;

})( window );

@frankwallis
Copy link
Owner

So I think the issue here is that plugin-typescript is treating the types option differently to tsc. plugin-typescript uses it to indicate that typings are available for this package under @types and will then make those typings available in files which import the module. I think that tsc uses it to mean that these typings should be made available in all files being compiled (ie they are peer dependencies)

The reason for this is that tsc is able to automatically find and include typings from @types when a module is imported but plugin-typescript needs to know if they are present in advance (due to the browser loading requirement)

@aluanhaddad - does this sound correct to you with regard to the tsc handling of the types option?

There are a few ways to solve this

  1. make typings in the types array available in all compiled files
  2. have a new option availableTypes to tell plugin-typescript which packages have typings under @types and revert the types option to have the same behaviour as tsc.
  3. force people to use either the files setting or /// <reference types="node"/> statements to include peer dependency typings

(1) is probably the easiest, but may mean that types are available in files which are not importing the module. (2) is a breaking change, but probably more correct. Probably I should implement (2) as a major change, although first I will find out what the impact of doing (1) will be.

@bennadel
Copy link
Author

bennadel commented Nov 9, 2016

@frankwallis thanks for the insight. I "mostly" understand what you're saying. For the time being, I'll just stick with using the files array since it at least seems to work.

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Nov 10, 2016

@frankwallis Yes, I believe your understanding of how tsc and tsserver use the types array is correct. This behavior is fairly new in TypeScript itself, and to be honest the whole feature is somewhat problematic.

For example if the types array is not specified, the compiler will include all @types packages in the node folder and make them available in all files.
The types array is actually a way to restrict this behavior, only including those packages specified but as you say, it is global to the compilation context.
They indeed behave like peerDependencies, but since they are not specified that way, version conflicts are rampant.
There are a number of open issues regarding this behavior for example, microsoft/TypeScript#11917.

I think it is an open question how this should behave, but my preference is for explicitness. This is one of the reasons I prefer jspm to npm.

plugin-typescript is treating the types option differently to tsc. plugin-typescript uses it to indicate that typings are available for this package under @types and will then make those typings available in files which import the module

I think this behavior is actually good but it does conflict with the behavior of tsc. One reason to keep the existing behavior is that @types packages mostly expose UMD style declarations that are global by default until they are imported as modules. In that sense the way plugin-typescript currently behaves seems to be more philosophically inline with SystemJS and jspm.

@frankwallis
Copy link
Owner

type-checking is no longer supported in 7.0.0 so this is no longer an issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants