← Back to context

Comment by jeswin

12 hours ago

First of all, congrats.

The website doesn't explain how it works in a lot of detail. I am the author of tsonic [1], a TS compiler that produces binaries via Clr NativeAOT (on Linux/Mac). The hardest parts were numbers (TS has no ints or shorts), Generics, and TS Utility Types. I've been on it for the last 6 months (almost every day); getting to near complete TS compatibility is a very long journey because of its expressiveness.

Add: A request is to explain how it works on the website. I did take a look at https://www.perryts.com/en/internals/ but are those techniques described really sufficient to express TS? Based on my experience, I must say I'm surprised. But the proof is in the pudding, and if it's compiling those examples it must be working somehow!

[1]: https://tsonic.org

Hey there, I'm going to check out your project because the comments here have me a little worried that OP's project might have some quality issues.

Two things I found a little confusing from the docs though:

I couldn't easily find a page describing what it can't do yet. I saw that it only works with a "strict, deterministic subset of TypeScript", but is there a page showing what's included and not included in that subset?

Also, what's an "ambient surface" in this context? Is that a compiler term I'm just not familiar with?

  • > strict, deterministic subset of TypeScript

    I'll add that page, thanks. Today, almost all of idiomatic TS is supported including most of its utility classes. Dynamic JS-style code is not supported, for example adding a function or a field into an object, prototype-based class modifications etc. I'll compile a list, and include it along with the large docs cleanup planned before v1.

    > Also, what's an "ambient surface" in this context?

    The idea is that when JS gets transpiled into C# (or Rust, upcoming), JS globals and built-ins are invalid. The native "surface" is C#, meaning the string is .Net's string type and the methods that you expect on JS strings would be missing. But when you opt in to a surface, such as the "JS surface", the compiler applies surface defined translations such as substring becoming SubString, either directly or via a companion helper class. This allows you to write against standard JS and Node APIs, instead of relying on the stdlib/builtins of the target framework (currently CLR). And you get the JS "stdlib" - console, JSON, Date, Map, Set etc.

    For example, all the projects you see under this use the JS surface: https://github.com/tsoniclang/proof-is-in-the-pudding/tree/m...

    • > Dynamic JS-style code is not supported, for example adding a function or a field into an object, prototype-based class modifications etc.

      FYI, just in case you didn't know, there is an ExpandoObject type in the System.Dynamic namespace that you could use to do this. IDK if you want to, but it's one of those less common .NET features that people tend to not be aware of.

      1 reply →

> The hardest parts were numbers (TS has no ints or shorts)

The easy way to handle that would be to just treat "number" as 64-bit float, since that is semantically how Javascript defines them. But that can hurt performance.

Another option is to define your own integer types

  • > Another option is to define your own integer types

    This is what I did. Most int usage is inferred, but if they had to define it explicitly, I make them import { int } from "@tsonic/core/types.js";