17

On our big enterprise project we faced a situation that seems not to be very well described in the articles and the posts available in the Internet.

We need to integrate our existing JavaScript infrastructural code that supports SPA with the code that is being developed by the other team on TypeScript. We can’t drastically change the approach (i.e. just pick a single language) for many political limitations and the development resources available. And we fully understand that’s probably it’s not a good idea to integrate two pieces of infrastructure together that are written on different languages.

Still we need to evaluate the impact and best practices of calling TypeScript from JavaScript code.

The justification that TypeScript is essentially compiled into JavaScript seems to be obscure because there are no trustful sources on information on the topic on how to properly consume that compiled JavaScript from handwritten JavaScript and what are the hidden caveats (or alternatives).

It also seems that the opposite situation when TypeScript code needs to call JavaScript is surprisingly very well described.

Any profound thoughts on the topic?

UPD

Specifically here is the list of questions we are seeking the answers now:

  • what will be the JavaScript shape of the TypeScript API that extensively uses generics, class hierarchies, interfaces?
  • are there any issues with bundling, minification, AMD?
  • is it possible to have the basic Angular controller written in TypeScript and the other JavaScript Angular controller that inherits the functionality from it? What will be the caveats?

Actually we think that we haven't surfaced all the questions yet. They've emerged just after a couple of hours of thinking on that topic.

xenn_33
  • 855
  • 1
  • 10
  • 25
  • 1
    Overall there is more documentation available on interfacing TypeScript to JavaScript because the other way round there are no problems and even the prototype-based inheritance is completely compatible (see also [TypeScript Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals)). I was recently collecting some links relevant to your "enterprise project" in http://programmers.stackexchange.com/a/260462/129832 – xmojmr Nov 21 '14 at 10:21

5 Answers5

26

The justification that TypeScript is essentially compiled into JavaScript seems to be obscure because there are no trustful sources on information on the topic on how to properly consume that compiled JavaScript from handwritten JavaScript and what are the hidden caveats

Consuming TypeScript from JavaScript is the same as consuming TypeScript from TypeScript, or JavaScript from JavaScript for that matter. For example, let's say you have a function in TypeScript:

function f(n: number) { return 'the number is ' + n; }

To call this function from TypeScript, you would write

var x = f(42);

To call this function from JavaScript, you would write

var x = f(42);

Let's say you have a class in TypeScript:

class MyClass { /* ... */ }

To use this class from TypeScript, you would write

var c = new MyClass();

To use this class from JavaScript, you would write

var c = new MyClass();

In other words, it's exactly the same. No guidance has been given because none is needed.

Ryan Cavanaugh
  • 209,514
  • 56
  • 272
  • 235
  • 2
    Thank you for the answer. The situation is trivial when you face somewhat like function that returns “Hello world!” or “Hello daddy!”. But it is not that trivial when someone in The Enterprise provided you the framework/infrastructural code in TypeScript that uses extensively generics, interfaces and inheritance. As we are just evaluating the caveats still we think that minification, bundling, AMD and other similar things may have great impact – xenn_33 Oct 17 '14 at 15:38
  • Can you post a more specific example then? – Phix Oct 17 '14 at 15:45
  • 1
    simply I can’t. The question isn't about a specific issue. The question is high-level and related to the strategy that needs to be developed. In the comment above some high-level considerations have been provided and we are seeking for a thoughtful explanation of different not-that-obvious aspects to be aware of (i.e. whether it is possible to have a base class for Angular controller in TypeScript and the other JavaScript Angular controller that inherits functionality from it) – xenn_33 Oct 17 '14 at 15:55
  • 4
    You're massively overthinking it. There really isn't anything more complex going on here. Everything you've listed is both possible and straightforward. – Ryan Cavanaugh Oct 17 '14 at 16:00
  • As for the current we haven't found the comprehensive answer to literally any concern I mentioned about in my comments above. saying that that is possible and straightforward is probably isn't enough then. I may probably need to update the original question with the concerns related to consuming generics, class hierarchies, minification, AMD and things of that nature – xenn_33 Oct 17 '14 at 16:16
  • Why on earth if that kind of a reverse integration is so damn simple it is not so aggressively advertised with examples, tutorials, labs and everything else that Microsoft usually promotes? I’m not telling that such kind of the advertisement is bad. Vice versa–it arms us with solid arguments against the FUD of the upper technical enterprise management that is usually very conservative in terms of listening to us, the developers who simply don’t have enough experience in TypeScript and can’t obtain the time budget to learn it because of the absence of solid references against that FUD.Deadlock? – xenn_33 Oct 17 '14 at 23:40
  • They are NOT exactly the same. For the function f above, if I call in typescript var x = f(null); I expect to get an error, because null is not a valid type (number). But in call from JavaScript it will not recognize type mismatch and it will not even have run-time error and will return 'the number is null' – Michael Freidgeim Jul 23 '21 at 14:27
13

Simply said, if you have to integrate/use a library which is written in Typescript in your own project which uses JavaScript, you will use the compiled JavaScript API!

You basically throw away everything which TypeScript brings in terms of benefit over pure JavaScript.

Meaning you don't have to care about anything specific to TypeScript, like generics etc. You only have to work with the compiled output of the TypeScript library...

To give you an example, go to http://www.typescriptlang.org/Playground Select "Walkthrough: Generics". On the right you should see the compiled JavaScript. It has no generics or anything special, it still is pure JavaScript. That's what you have to deal with...

to your "specific" questions:

  • what will be the JavaScript shape of the TypeScript API that extensively uses generics, class hierarchies, interfaces? See above. It will be plain good old Javascript. No difference for you.
  • are there any issues with bundling, minification, AMD? No, because compiled TypeScript is plain JavaScript and can be minified etc...
  • is it possible to have the basic Angular controller written in TypeScript and the other JavaScript Angular controller that inherits the functionality from it? What will be the caveats? Yes of course you can do whatever you want with the compiled JavaScript.

The only disadvantage of using the compiled JavaScript from Typescirpt is, that you throw away the awesome features TypeScript can give you, like... types... If the other team is already on that route, you may want to consider to write your part in TypeScript as well ;)

MichaC
  • 13,104
  • 2
  • 44
  • 56
  • Thanks for pointing out the playground that acts more like a case study of how TS gets compiled into JS. It gives just the basic clue. Still in the assumption that we are developing the infrastructural code for a large enterprise app some concerns remain vague.Will we face any breaking changes in the future of how TS gets compiled in JS with a newer version of TS? What happens if we decide to use newer version of Angular? Ultimately – will our code be compatible with ECMAScript6 in the future? – xenn_33 Oct 18 '14 at 10:46
  • Originally I was seeking the answers to these concerns with my initial question but it seems that we have to reveal them ourselves (if time budget permits - otherwise we will simply propose not to use TS) – xenn_33 Oct 18 '14 at 10:48
  • 2
    well in general it is pretty hard to predict what the future of TS or Angular will bring, but just think about what happens to your javascript if Angular implements breaking changes? You'd have to change your JavaScript. So that's not a reason not to use TS right? ;) Instead, it will be a lot easier to refactor the TS code because of the tooling available... You can also choose which standard (ECMAScript version) you want to target when compiling TS. So if you want to go with the new version, TS is absolutely ready for that and already supports certain features... – MichaC Oct 18 '14 at 11:10
  • You’ve got it probably absolutely right. We just want to produce a predictable roadmap for the project of almost a hundred enterprise developers on how to construct their APIs for the infrastructural and application-level front-end code to face minimum issues in the foreseeable future. Currently we have much more JS code and just a proposal to introduce some degree of TS code there, not rewriting everything in TS. Your point on the refactoring and tooling was absolutely correct. – xenn_33 Oct 18 '14 at 11:35
  • So probably we need to end up with weighting these benefits against the drawbacks related to the additional aspect that brings some degree of unpredictability (TS) – xenn_33 Oct 18 '14 at 11:36
4

I think is not a Typescript problem.

You could see the same 'issue' (issue,not a problem) with Cofeescript , dart, traceur , or any other transpiler.

Javascript as a platfom, is very susceptible to devs's experience, language understanding and skills. (like any other language? )

If someone has a hardtime reading the TS generated JS (that IMMO is pretty human friendly ) I don't think it will have better luck reading hand-coded messy JS.

Plus, you always have the TS's source code with the interfaces and more natural OOP manners.

the benefits of incorporating OOP and structure outweight the cons(if there is any).

IDE support is great (Webstorm , Visual Studio) , you can actually refactor!

And you have scoped lambdas :)

The next iteration EcmaScript will be very much like what is TS today (without optional type saftey and a few niceties).

What is gonna happen if somebody in the 'Js team' jump to ES6 with traceour or whatever other thing, will you care?. You will simply stick to the api provided by the module and work with that.

Interfaces and Generics and washed up no trace of them on the JS side. its *optional design time help.

And regarding the budling and minification thing, it will be the same as with JS , no difference , + you could jump one step with TS copilling everything to 1 outputfile

IMMO the solution is level-up , modularize(serioulsy), tests(very helpful if written with self documenting puprposes) and Documentation.

Dan
  • 2,818
  • 23
  • 21
4

This actually not all too complicated. . . the first thing you have to understand is that the component is created as an object by angular, and it contains all the data, components, objects and stuff from your api's so you can't just go have JavaScript make a new one, it will be empty and won't actually have your form data in it.

In order to remedy this, you need to add an asset to your site, a simple file with one variable in it is fine, then add it to your app, then import it and set it in your init

i've outlined how you import a JS variable into angular below, but here's a link with a bit more detail:
How to call JavaScript functions from Typescript in Angular 5?

so add the js file containing:

var formComponent = null;

then add it to your app (angular.json)

"scripts": [
    "src/assets/js/formScripting.js"
]

then import it to your component right under your "imports"

declare var formComponent: any;

then assign your object on your init and destroy

ngOnInit() {
    formComponent = this; 
}

ngOnDestroy(): any {
    formComponent = null;
}


//a function in your class that you want to call for test purposes
doAngularThing() {
    console.log('Typescript called from JS:')
}

from that point on, in ANY javascript function all you have to do is call:

formComponent.doAngularThing();

since the formComponent object was assigned to this, it's a pointer to the angular object that loaded your compoonent

Mike A.
  • 1,438
  • 13
  • 11
2
  • What will be the JavaScript shape of the TypeScript API that extensively uses generics, class hierarchies, interfaces?

Typescript erases type information during compilation, including generic parameters. This means that you just omit the type parameters in your javascript.

  • Are there any issues with bundling, minification, AMD?

No.

  • Is it possible to have the basic Angular controller written in TypeScript and the other JavaScript Angular controller that inherits the functionality from it? What will be the caveats?

Yes, it's possible. There are no caveats.

General Solution:

In general, there is a simple solution for any interoperability concern between typescript and javascript. By the time the interoperating happens, the typescript has all been compiled to javascript. So if you're worried about how to consume typescript, just compile it to javascript. Then you are interoperating with javascript.

recursive
  • 83,943
  • 34
  • 151
  • 241
  • Still things seem to be not that simple. E.g. here http://www.walkercoderanger.com/blog/2014/02/typescript-isnt-the-answer/ people were talking on the issue with 'this' keyword that we have to probably be aware of. – xenn_33 Oct 17 '14 at 16:48
  • Are you talking about interoperability with javascript? Or flaws in javascript? The criticism about `this` at that blog is that `this` in typescript acts just like `this` in javascript. How could it possibly be simpler for interoperability? – recursive Oct 17 '14 at 16:51
  • The blog showed the 'this' used in the scope of a class in TypeScript. How could it behave like 'this' in JS when there are no classes in JS? That brings us closer to the matter of the discussion - is there a comprehensive set of rules on how to properly set our expectations from the compiled code or we just need to relax and accept the vague statement that 'everything behaves in the similar fashion'? Another case are enums. We just need to reveal that we have to use integer codes in JS instead of names in TS – xenn_33 Oct 17 '14 at 16:59
  • For a background on how `this` works in javascript, see [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). And I'm not sure why you think you can't use enum names from typescript in javascript. You can. There is an official set of rules for how typescript interoperates with javascript. It's the typescript language specification. – recursive Oct 17 '14 at 17:06
  • 1
    It is probably a nice idea if still someone writes an article that will eliminate the FUD associated with adoption of any modern technology by enterprise teams where you usually face a lot of pushback. And decrease the learning curve related to the integration. Surprisingly nobody did that so far. – xenn_33 Oct 17 '14 at 17:29
  • 1
    Until today, I didn't realize there was any FUD. In any case, this document may help. It's quite readable as far as language specs go. http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf – recursive Oct 17 '14 at 17:54