Skip to content
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

require untyped JS file #5049

Closed
EToreo opened this issue Oct 1, 2015 · 22 comments
Closed

require untyped JS file #5049

EToreo opened this issue Oct 1, 2015 · 22 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@EToreo
Copy link

EToreo commented Oct 1, 2015

I am working with typescript 1.6.2 and trying to write some newer sections of code with it. The problem is, I need to consume other native JavaScript code I have already writen and am not prepared to convert to TypeScript just yet.

So I would like to do something like this (where lib/helper.js is a file I'm not ready to convert to TS yet):

var helper = require('../lib/helper');

When I try to compile this, I get an error: error TS2304: Cannot find name 'require'

To get around this I add:

declare function require(path: string) : any;
var helper = require('../lib/helper');

Is there a way to have TypeScript use an untyped common JS file without this "hack"? Without it, it seems that TypeScript is only good for new projects or 100% adoption. I would like to see a path that allows me to casually convert my very large project to it a piece at a time.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 1, 2015

#4792 should do the trick. there is PR: #4826 will allow you to import your JS modules, and the TS compiler will "understand" the shape of the module from your .js files and let you code against it in your .ts files.

can you elaborate on what your .js module looks like? are you using ES6? are the module exports fairly static (i.e. exports = function(){...}, or exports.prop = value) or more dynamic (e.g. Object.keys(another).forEach(k => { module.exports[k] = another[k]; });)? are they library code, or your own modules? how are you distributing them? separate npm packages? do you concatenate? how about typings for your users? is that something of interest?

@EToreo
Copy link
Author

EToreo commented Oct 1, 2015

Thanks for the reply.

Not using ES6 anywhere. The exports are very static. They are my own modules. I don't deliver them, they are just run on a server that hosts a product I sell a subscription to. In the future, I would like to bundle it all up and sell it for "behind the firewall" use - but that's neither here or there at the moment.

I'm trying to introduce unit test for the first time to this product and I would like to write these tests in TypeScript. Eventually, I would like to convert the entire product to TypeScript, but that won't be for a while.

Does this give you a good feel for what is going on and my end goals? Here is the example from my experiments I am using to see if I can use TypeScript for this purpose:

/// <reference path="../../typings/mocha/mocha.d.ts" />
/// <reference path="../../typings/chai/chai.d.ts" />

/**
 * Module dependencies.
  */
import chai = require('chai');

// require hack
declare  function require(path: string) : any;

// require untyped library file
var helper = require('../../lib/helper');

/**
 * Globals
  */

var expect = chai.expect;

/**
 * Unit tests
  */
describe('User Model Unit Tests:', () => {

   describe('2 + 4', () => {
      it('should be 6', (done) => {
         expect(helper.add(2, 4)).to.equals(6);
         done();
      });

      it('should not be 7', (done) => {
         expect(helper.add(2, 4)).to.not.equals(7);
         done();
      });
   });
});

@DanielRosenwasser DanielRosenwasser added the Question An issue which isn't directly actionable in code label Oct 1, 2015
@DanielRosenwasser
Copy link
Member

@mhegazy probably has better advice, but here's the route I'd probably go with for now.

I would probably create a .d.ts file that describes the structure of your module. Gradually, as you use things from that module, you can define/export them from the .d.ts file. Initially, this is a little time-consuming, but it gets better as you go along and it pays off next time you have to use that module.

If you really don't want to have to think about using it too much, just define your values with type any or Function and come back to them later.

So for instance, you start writing your unit tests for add. Well you'll need to actually reference add, so in "../../lib/helper.d.ts" you write

export function add(a: number, b: number);

And progressively work with that.

Now let's say you need to test that module's foo.bar.baz.frip() method. Uh, what was the specific structure for that again? What else is on a bar? It's pretty nested.

You don't have to go all out. It pays off later if you do, but if you really need to keep your momentum, you can write

export var foo: {
    bar: any;
};

and come back later instead of fleshing out all your types now:

export interface Foo {
    bar: Bar;
}

export interface Bar {
    baz: Baz;
}

export interface Baz {
    frip(): void;
}

export var foo: Foo;

@EToreo
Copy link
Author

EToreo commented Oct 1, 2015

@DanielRosenwasser I wouldn't mind doing that (I might not even mind being forced by TypeScript to do that), but I still can't figure out how to get the require statement to take a path relative to my files ("./lib/helpers.js"). It feels like the imoprt/require from TypeScript assumes all your code is in node_modules or ts files. Without #4826 it seems I am stuck with the hack.

@mhegazy
Copy link
Contributor

mhegazy commented Nov 13, 2015

but I still can't figure out how to get the require statement to take a path relative to my files ("./lib/helpers.js")

this should be working today. just do not include the extension .js in the file path.

@mhegazy mhegazy closed this as completed Nov 13, 2015
@wclr
Copy link

wclr commented Sep 3, 2016

Do I understand correctly that that to be able to require helper.js

import helper = require('../lib/helper');

I still need to have helper.d.ts near helper.js file? Otherwise for me it says that can not locate the module.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 3, 2016

You should not need this if you are using TS2.0. Do you have a jsconfing file?

@wclr
Copy link

wclr commented Sep 3, 2016

I'm on TS 2.1dev, No I don't have jsconfig, only tsconfig:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strictNullChecks": true,
    "noImplicitAny": true,    
    "experimentalDecorators": true
  },
  "formatCodeOptions": {
    "indentSize": 2,
    "tabSize": 2
  },
  "exclude": ["**/node_modules"]
}

@mhegazy
Copy link
Contributor

mhegazy commented Sep 3, 2016

Set maxNodeModuleJsDepth to the desired module depth you want to follow js files for; by default it is zero.

@wclr
Copy link

wclr commented Sep 4, 2016

@mhegazy that doesn't seem to help, if there is no aws-store.d.ts:
image
and import require doesn't work either:
image

@mhegazy
Copy link
Contributor

mhegazy commented Sep 6, 2016

can you share a sample repro project?

@wclr
Copy link

wclr commented Sep 6, 2016

@mhegazy this structure 3 files:
/tsconfig.json

{
  "compilerOptions": {    
  },
  "include": ["src/*"]
}

/src/index.ts

import x from  './jsmodule'

/src/jsmodule.js

  export default {}

image

I wonder what is wrong

@mhegazy
Copy link
Contributor

mhegazy commented Sep 6, 2016

you need to set "allowJs": true.

@wclr
Copy link

wclr commented Sep 6, 2016

@mhegazy hm, it worked on bigger project eventually after window reload, I think I tried this, but it didn't for me) ok thank you for your help

@wclr
Copy link

wclr commented Sep 7, 2016

Hm it seems that with allowJS: true compiler ignores all the typing files "*.d.ts" (custom/installed using typings tool).

@mhegazy
Copy link
Contributor

mhegazy commented Sep 7, 2016

it should not. allowjs tells the compiler to pick .js files as well as .ts and .d.ts. make sure your include and exclude in the tsconfig.json are set correctly.

@wclr
Copy link

wclr commented Sep 7, 2016

Have only:

"exclude": ["**/node_modules"]

no, include.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 7, 2016

run tsc --listFiles do you see your .d.ts files?

@wclr
Copy link

wclr commented Sep 7, 2016

Yes I see along with a huge list of js files, but after I turn on allowJS it can not find modules trypings for which are in "typings/index.d.ts" (installed using typings tool)

image

If I remove "allowJs" it works ok.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 7, 2016

i can not seem to reproduce this locally. can you share a sample project where i could debug the issue.

@wclr
Copy link

wclr commented Sep 7, 2016

@mhegazy ok it woks, I think maybe the problem was that it there where to many JS files to to handle, at least I have to reload vscode because it consumed 50% CPU,, probably allowJS is not a good option for a big project, though after reload it seem to work ok. Thank you again)

@mhegazy
Copy link
Contributor

mhegazy commented Sep 7, 2016

keep in mind that with allowJs the compiler will load files that it did not load before. so a good thing to do after enabling it is to look at your files before enabling allowJs and after with tsc --listfiles. if you see files that should not be there add them to the exclude list.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants