Skip to content

Support shorthand ambient module declarations and wildcard chars in module names #6615

Description

follow up on #6614

Related issues: #247 (comment), #5787, #2709, #6371 (comment)

Problems:

  • Can not easily specify a loader extension for json or css (e.g. `json!a.json); currently every resources needs to have its own declaration
  • Problem with migrating to .ts, with modules that do not have typings, and users just want to get by

Proposal:

  • Allow for short hand module declarations:

    declare module "foo";

    to be equivalent to:

    declare module "foo" {
        var _temp: any;
        export = _temp;
    }
  • Allow module names to have a wildcard character and match that in lookup

    declare module "json!*" {
        let json: any;
        export default json;
    }
    
    import d from "json!a/b/bar.json";
    // lookup:
    //    json!a/b/bar.json
    //    json!*
  • Additional the module "*" would allow for matching all unknown modules in the system, which can be used as a way to suppress all missing module errors

    declare module "*";
    
    import d from "some\unknown\module"; // no error, d is any
  • Report no-implicit-any errors for modules declared using the shorthand notion
    Open issue: is this reported on declaration or use sites

Activity

  1. mkosieradzki commented on Jan 25, 2016

    @mkosieradzki

    Epic solution for #2709 !

  2. dfaivre commented on Jan 25, 2016

    @dfaivre

    Nice to see this is being worked on -- looks like an interesting solution that neatly captures all the outstanding requests.

    Personally, I'd also like to see a compiler flag for the declare module "*"; use case -- it seems a little more natural, something like noExplicitAny, except for modules.

    Thanks again for all the great work!

  3. nillis commented on Jan 25, 2016

    @nillis

    +1
    Great solution! Looking forward to be able to delete all modules I created manually to keep the compiler happy

  4. ivogabe commented on Jan 25, 2016

    @ivogabe
    Contributor

    Allow for short hand module declarations:

    declare module "foo";

    to be equivalent to:

    declare module "foo" {
        var _temp: any;
        export = _temp;
    }

    I think that this doesn't cover all cases, as this fails currently:

    declare module "foo" {
        var _tmp: any;
        export = _tmp;
    }
    declare module "bar" {
        import { x } from "foo"; // Error: Module foo has no exported member x
        import y from "foo"; // Error: Module foo has no default export
    }
  5. mhegazy commented on Jan 25, 2016

    @mhegazy
    ContributorAuthor

    thanks Ivo Gabe de Wolff (@ivogabe). the idea is you can use this module in any way you want and you just get any with no error. So the proposal should be updated to:

    declare module "foo" {
        var _temp: any;
        export = _temp;
        export default _temp;
    }
  6. amcdnl commented on Jan 26, 2016

    @amcdnl

    I like the idea, but I think 2.0 is too far for this. This can help to solve so many issues the community has with lack of typings/etc.

  7. kitsonk commented on Jan 26, 2016

    @kitsonk
    Contributor

    Thanks, this certainly address my use cases!

    Austin (@amcdnl), 2.0 is the next release after what is currently being stabilised as feature complete.

  8. geirsagberg commented on Jan 26, 2016

    @geirsagberg

    This is great! (GitHub really needs an upvote button.)

  9. jack4it commented on Jan 26, 2016

    @jack4it

    Two questions:

    • Are the current proposals able to cover the following scenario?
    import "xyz.less";

    Can I do this?

    declare module "xyz.less";
    • Will this syntax be one of the proposals?
    import template: string from "template.html";
  10. kitsonk commented on Jan 26, 2016

    @kitsonk
    Contributor

    Jack Ma (@jack4it) if I understand the proposal correct:

    declare module "xyz.less";

    Would automagically make the import xyz from 'xyz.less' or import * as xyz from 'xyz.less' as type any. If you are just importing for side effects, like in your first statement, it is entirely up to what module loader you are using and how it is configured. Almost any module loader will require some sort of plugin (though obviously using NodeJS's registry can absolve people from having to consider this, but that doesn't make for very "portable" code).

    If you wanted the last to work, you would want to declare an ambient module like this:

    declare module '*.html' {
        const template: string;
        export default template;
    }

    And you module loader would have to ensure that it process things appropriately.

    Personally, I think any more automagic behaviour would be dangerous.

  11. mhegazy commented on Jan 26, 2016

    @mhegazy
    ContributorAuthor

    Will this syntax be one of the proposals?
    import template: string from "template.html";

    No. 1. is it makes it much harder to update your definitions later on as now you have sprinkled template: string throughout your code base, and 2. type annotations will need to be supported on all import forms not only default imports import d from "mod" but for namespace, and property imports, and that would add yet another variant to the import syntax, and we already have plenty.

  12. 54 remaining items

  13. mayerwin commented on Nov 21, 2016

    @mayerwin

    Mohamed Hegazy (@mhegazy) Thanks 👍, I wasn't aware of the possibility to declare the whole module as any. It works. It would deserve to be highlighted more to help people know how easily they can tap into the JS ecosystem if they make the move to TS.

  14. wenbaofu commented on Feb 1, 2017

    @wenbaofu

    Mohamed Hegazy (@mhegazy) : hi , I had a question about this issue
    I try like this:
    in file.ts I write

    /// <reference path="require.d.ts" />
    import JsonInfo from "json!files.json"; 
    

    I am not sure /// need or not

    then I new a file called require.d.ts

    declare module 'json!*' {
        const value: any;
        export default value;
    }
    

    and the files.json is in base dir like below

    index.html
    files.json
    app/
       -  file.ts
       -  require.d.ts
    

    and I get below error
    image
    image

    but I can access the json file
    image

    I check the https://www.bountysource.com/issues/41187251-ambient-module-declarations-with-wildcards-giving-errors-official-docs-example-not-working
    and http://www.typescriptlang.org/docs/handbook/modules.html#shorthand-ambient-modules

    now I have no answer,hope your reply,tks

  15. wenbaofu commented on Feb 1, 2017

    @wenbaofu

    Andy (Andrewkraft) (@Andy-MS) : thank you first for answer

    you mean systemjs (module loader) not support?

    now I just use sample of hero to test json,I think loader maybe ok

    this is my config

    (function (global) {
        System.config({
            paths: {
                // paths serve as alias
                'npm:': 'node_modules/'
            },
            // map tells the System loader where to look for things
            map: {
                // our app is within the app folder
                app: 'app',
                // angular bundles
                '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
                '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
                '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
                '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
                '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
                '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
                '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
                '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
                // other libraries
                'rxjs':                      'npm:rxjs',
                'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
            },
            // packages tells the System loader how to load when no filename and/or no extension
            packages: {
                app: {
                    main: './app.module.js',
                    defaultExtension: 'js'
                },
                rxjs: {
                    defaultExtension: 'js'
                },
                'angular-in-memory-web-api': {
                    main: './index.js',
                    defaultExtension: 'js'
                }
            }
        });
    
        "rxjs": "5.1.0",
        "systemjs": "0.20.5",
        "zone.js": "^0.6.25",
        "json-loader" : "^0.5.4"
    

    pls help check if systemjs don't support or not or other problem?

  16. aluanhaddad commented on Feb 1, 2017

    @aluanhaddad
    Contributor

    SystemJS uses postfix plugin syntax: e.g

    import JsonInfo from "files.json!node_modules/json-loader/index.js";

    There has been discussion of supporting postfix and prefix notation but I do not believe it is currently supported.

    See systemjs/systemjs#1092

  17. aluanhaddad commented on Feb 1, 2017

    @aluanhaddad
    Contributor

    Note that using package configuration as in

    packages: {
      app: {
        main: './app.module.js',
        defaultExtension: 'js',
        meta: {
          '*.json': {
            loader: 'my-loader'
          }
        }
      },
      ....

    with no plugin specifier as in

    import JsonInfo from 'files.json';

    is the preferred approach

  18. wenbaofu commented on Feb 1, 2017

    @wenbaofu

    Aluan Haddad (@aluanhaddad) : if like

    meta: {
          '*.json': {
            loader: 'my-loader'
          }
          import JsonInfo from 'files.json';
    

    will give the error with cannot find the module "files.json"

    image

    and json-loader is same
    image

  19. wenbaofu commented on Feb 1, 2017

    @wenbaofu

    Andy (Andrewkraft) (@Andy-MS) : yeah,it works(not give 404 error) , but when I print it , give undefined; when I give complex json, like { "name" : "test"}, then it will printf
    image

    image

    file.ts

    import JsonInfo from "files.json"; 
    console.log(JsonInfo);
    

    files.json

    {
      id : 3
    }
    

    module

    declare module '*.json' {
        const value: any;
        export default value;
    }
    

    systemjs

    meta: {
                '*.json': {
                    loader: 'my-loader'
                    }
                }
    
  20. aluanhaddad commented on Feb 1, 2017

    @aluanhaddad
    Contributor

    That is invalid JSON.

  21. drewlsvern commented on Mar 9, 2017

    @drewlsvern

    I'm not sure if anyone solved this, but I was able to get it to work using 奔跑在路上 (@wenbaofu) examples above. I just provided it valid json and used systemjs-plugin-json as the loader.

  22. added a commit that references this issue on Mar 23, 2017
  23. Jack-Works commented on May 27, 2017

    @Jack-Works
    Contributor

    Umm, can I do something more differently?
    Like

    declare module "*.module.js" {
    	var loader: AsyncModuleLoader
    	export = loader
    }

    I use this type of declaration to type async module(by webpack), but not success

  24. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CommittedThe team has roadmapped this issueFixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions