
Moving from TypeScript to Rust / WebAssembly - nicolodavis
https://nicolodavis.com/blog/typescript-to-rust/
======
hardwaregeek
Whenever I write Rust, I have a lot of fun, but I'm still not sold on it for
most web dev.

The analogy that comes to mind is that Rust is a really nice sports car with a
great engine. It handles like a dream and you can feel the powerful engine
humming while driving it. With the right open road, it's a great time. You can
really optimize code, make great abstractions and work with data easily.

Unfortunately, web dev generally isn't a wide open road. It's a lot of little
turns and alleys and special cases. Driving Rust in web dev is a lot of
accelerating only to screech to a halt. I wrote a backend API for a side
project in Rust. And true to what I said, Rust handled like a dream. But I
didn't need the power. I spent most of my time screeching to a halt worrying
about the plumbing between the various immature Rust libraries. And that's on
the backend, which is way more mature compared to the frontend Rust libraries.

Judging by this post, OP managed to find a great open road in web dev to use
Rust. I only wish I could find one as worthwhile.

~~~
aphextron
This really nails why languages like PHP and Ruby have won out over static
typed, compiled ones for application level web development. The web is a
massive collection of disjointed, loosely coupled APIs that all (just barely)
interoperate to provide a massive array of functionality. Languages that tend
to work well with it are those that are highly flexible around the corner
cases of these technologies, and allow you to quickly iterate through the
process of gluing them together.

~~~
rubber_duck
Won ? Ruby fell off a cliff once it got to a point where people had to
maintain that shit in production - I'm currently working on a large mature RoR
codebase and I'm switching jobs ASAP because it's incredibly painful to work
with and feels like a dead end career wise - and I like the gig otherwise -
good product and a decent team - but the technology is draining so much of my
life energy on nonsense it's ridiculous. And the language is built for
unmaintainability - standard functions being abbreviated to a single letter, 2
or 3 aliases for a single standard function (map/collect and such), Rails
overriding the conventions of the language (! postfix). And then there's the
architectural retardation of fat models, fat controllers and using mixins
("concerns") completely break encapsulation - all actively killing code reuse-

PHP has long been a meme and is mostly legacy stuff or bottom tier work.

Dynamic languages are adding static optional static typing because the value
provided by tooling as the projects scales is undeniable.

It took ES6/TypeScript to drag JS out of the dump that it was with every
library adding its own take on a class system - the maintainability jump from
ES5 to TS is incomparable for anything larger than 1k LOC

~~~
wwright
I say this a lot, but if you are this irritated by Rails, then you ought to
see the 20+ year old legacy C/C++ some of us get to work with ;)

~~~
cmrdporcupine
This is one nice thing about working at Google. We have C++ codebases that are
20 years old, but you'd never be able to tell because they are still
continuously worked on and even if not there's a team of people at Google who
constantly run company-wide refactorings and the like to modernize things.

~~~
gen220
This is, IMO, one of the most underrated aspects of the monorepo, that has
such a valuable impact over time.

It only takes a handful of extremely passionate engineers (and I really mean a
handful, like less that 2% of engineers in an org) to raise the quality-floor
of the _entire_ codebase.

~~~
lifeisstillgood
For sanity, sustainability and fairness I would rather that read

It only takes a handful of extremely passionate engineers > It only takes a
handful of paid engineers, full time assigned to the task

~~~
gen220
Anecdotally (I don't work at Google, and this might not apply there because
it's such a _large_ company): At the monorepo companies I've worked at, of the
2% passionate I mentioned, maybe half have naturally gravitated towards
working FT on the infra teams, the other half make very occasional but
astronomical contributions, while working full-time on an actual product.

What I mean to say is that with a monorepo, you leave the door open to
essentially passion-driven contributions made by the other half of that 2%. In
non-monorepo environments, the barrier to uniform adoption is too high for
someone that _isn 't_ full-time assigned to the task to justify.

Some people are genuinely passionate about this stuff, and _want_ to take on
the task of migrating the entire code base, because it's a fun challenge and
it'll improve their day-to-day work every day for the remainder of their
employment. They're very rare, but they do exist, and with a monorepo those
people are better-equipped to drag the company forward.

~~~
lifeisstillgood
I don't get this - changing the _code_ is not the problem - this is a
political / marketing issue.

I have some news - passion is not enough, and there are more than 2% of people
working on things they are passionate about - it only 2% get lucky.

I can think of a few instances in my recent career at large monorepo company
where I have built something on the scale of "passionate, could improve our
working lives"

One died because ... well I gave up, two are used locally by my team and those
I could persuade, whilst other solutions built by others for the same fix have
gone on to be blessed officially, (ie replaced by grassroots competition) and
one was replaced by a fully mandated and funded project that spotted the need
and just steamrollered over all the local fixes.

One is still outstanding and I think well worth pushing still.

But I don't dream of the big win where suddenly the Board says "why, without
your glasses Miss Moneypenny you look ravishing".

I get paid, I work, and I try and make the world a bit better where I can. I
am passionate about it. But i don't write blog posts about how passionate I
am.

Maybe I should :-)

------
chjj
> webassembly is faster than javascript

Everyone says this, but I would dispute it as misleading in a lot of cases.
I've been experimenting a lot with wasm lately. Yes, it is faster than
javascript, but not by all that much.

It's the speed of generic 32 bit C. It leaves a lot to be desired in the way
of performance. My crypto library, when compiled to web assembly, is maybe
2-3x the speed of the equivalent javascript code. Keep in mind this library is
doing integer arithmetic, and fast integer arithmetic does not explicitly
exist in javascript -- JS is at a _huge_ disadvantage here and is still
producing comparable numbers to WASM.

This same library is maybe 15 or 16 times faster than JS when compiled
natively, as it is able to utilize 128 bit arithmetic, SIMD, inline asm, and
so on.

Maybe once WASM implementations are optimized more the situation will be
different, but I am completely unimpressed with the speed of WASM at the
moment.

~~~
daninet
I also have a WASM crypto library, focused on hashing algorithms:
[https://www.npmjs.com/package/hash-
wasm#benchmark](https://www.npmjs.com/package/hash-wasm#benchmark)

I was able to archive 10x-60x speedups compared to the performance of most
popular JS-only implementations.

You can make your own measurements here:
[https://csb-9b6mf.daninet.now.sh/](https://csb-9b6mf.daninet.now.sh/)

~~~
chjj
Yeah, hashing in WASM seems to be fine in terms of speed, though 60x faster
does still sound surprising to me. Hashes with 32 bit words (e.g. sha256) can
be optimized fairly well in javascript due to the SMI optimization in engines
like v8. I should play around with hashing more.

I was in particular benchmarking ECC, which is much harder to optimize in JS
(and in general).

Code is here:

JS: [https://github.com/bcoin-
org/bcrypto/tree/master/lib/js](https://github.com/bcoin-
org/bcrypto/tree/master/lib/js)

C: [https://github.com/bcoin-org/libtorsion](https://github.com/bcoin-
org/libtorsion)

To benchmark:

    
    
        $ git clone https://github.com/bcoin-org/bcrypto
        $ cd bcrypto
        $ npm install
        $ node bench/ec.js -f 'secp256k1 verify' -B js
    
        $ git clone https://github.com/bcoin-org/libtorsion
        $ cd libtorsion
        $ cmake . && make
        $ ./torsion_bench
        $ make -f Makefile.wasi SDK=/path/to/wasi-sdk
        $ ./scripts/run-wasi.sh torsion_bench.wasm ecdsa

------
amitport
Hi Nicolo,

Here are my two (or more) cents:

1 - Javascript is fast enough for your use case. No one will notice the
difference in a board game website.

2 - AI should probably be implemented in python anyway. As ugly as python can
be, you shouldn't fight the world; there are too many free advanced AI algo
implementations in python out there.

3 - Regarding "Limitations of TypeScript" (strict typing / data validation /
error handling): first of all arguable claims, but moreover, even if you think
rust is better in these concerns, they are not important enough to justify
reimplementation, disregarding away typescript's advantages and taking the
risk involved in a new language and toolset. Yes, I can see the appeal as a
programmer to learn new stuff, but seriously you should have much better
reasons to rewrite existing code.

BTW, also, if I would think of a rewrite, I would have gone with scala or
python, both are slower on the web, but seriously, it will not amount to
anything meaningful in your use-case. Scala has better typing, and contextual
abstraction is a killer feature for DSLs like game mechanics specification.
Python is the lingua franca of AI, and pypy has greenlets [1]! Which is much
cooler than people seem to realize. Specifically, it should allow writing
immutable redux-like command pattern operations, as regular code, without the
weird switches everywhere.

BTW2, I've contributed to boardgame.io, please consider staying with open
source. We can build something like boardgame-lab together.

[1]
[https://greenlet.readthedocs.io/en/latest/](https://greenlet.readthedocs.io/en/latest/)

~~~
nicolodavis
Hey Amit, good to hear from you!

> Javascript is fast enough for your use case. No one will notice the
> difference in a board game website.

No, actually. Have you seen how long boardgame.io's MCTS bot takes to make a
Tic-Tac-Toe move? Not the end of the world, but certainly in need of
improvement.

~~~
amitport
Yes, but AI search algorithms like MCTS are slow in general. Even with C, it
will be very slow when you want the AI to be smart and consider many actions.
IMO, you should train using python libs like [1] and move it to the browser
with something like [2] OR run AI in the server. YES definitely writing an AI
lib for the browser is a great goal, and as a programmer, it is super
interesting. Still, it is tough, and time-to-market is much more crucial, as
the entire codebase will change once it will interact with actual people.

[1] [https://github.com/datamllab/rlcard](https://github.com/datamllab/rlcard)

[2] [https://onnx.ai/](https://onnx.ai/)

~~~
skybrian
Other than solved games like tic-tac-toe, game-playing bots can always use
more performance because if you can search more efficiently, your bot gets
smarter. Sometimes supposedly more sophisticated algorithms end up making
things worse because they slow down the search.

It's an unusual area where functionality (what answer you get) and performance
can't be separated. This is still true on the server.

~~~
amitport
To be clear, I'm not talking about the server implementation only about
implementation on the browser.

And of course, Rust and C are faster than javascript, and it will be
noticeable on search algorithms, but IMO, it will not cause user loss. It is
smarter to get to the stage you have those users as fast as you can to
validate this need.

So I would not go into implementing new AI libs in rust as part of a turn-
based game engine just for the performance gain--mainly because it is a
tougher project than building a turn-based game engine!

I would search for existing, viable solutions. As I said before, this includes
server AI and server trained models running on something like tensorflow.js.
Additionally, I will also try to research browser libs that may use compiled
webassembly and webGL. In any case, I think it's not wise to build your own
for this purpose.

------
lacker
_[TypeScript] does not actually ensure that the data you are manipulating
corresponds to the type that you have declared to represent it. For example,
the data might contain additional fields or even incorrect values for declared
types._

This is only a problem if you are mixing untyped code with typed code, isn't
it? Like when you are parsing JSON, you need to do typechecking right then,
rather than just using an "any" type. The only other situation I have run into
this in practice with TypeScript is when I'm using a library that has slightly
misdefined types.

~~~
filleduchaos
> This is only a problem if you are mixing untyped code with typed code, isn't
> it?

I find it a bit strange that people talk about this as "only a problem", as
though it was some weird niche edge case and not an ever-present issue. The
written-in-plain-JS ecosystem completely dwarfs the written-in-TypeScript one;
unless you're doing something rather trivial you're quite likely to end up
depending on a library that barely had the shape of its objects in mind during
development, with typings (if they're even present) that were contributed by
someone that's almost definitely not the actual library author.

Of course, if you're competent enough you can correct typings and always
remember to run runtime checks on data that doesn't come from you and so on.
But it's too easy for a beginner to fall into traps like mishandling data that
comes from a dependency (especially when it's buggy/ostensibly has typings) -
in my opinion, there should be a first-party compiler/linter option to enforce
checks on any `any`.

~~~
lacker
You don't have to depend on badly-written untyped third-party libraries, just
because there are a lot of them out there. Many projects and companies will
avoid doing so. This is especially reasonable if your comparison is switching
to a language like Rust; there are probably fewer third-party libraries
available in Rust overall than there are libraries with accurate TypeScript
definitions available.

~~~
filleduchaos
"Badly-written" is of course subjective, but as for untyped/loosely typed I
think it's a bit difficult to claim that people are avoiding using them when
(for example) the typings for an obviously popular library like Express are
chock-full of `any` types[0]. Including several (like request bodies) that
should instead be `unknown`. I'm sorry but it's rather naïve to expect a
beginner to TypeScript, especially one that's coming from JS, to not trip up
at all using typings like that and a compiler/language spec that implicitly
casts things declared as `any`.

0\.
[https://github.com/DefinitelyTyped/DefinitelyTyped/blob/mast...](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express-
serve-static-core/index.d.ts)

------
melling
I don’t know Rust and haven’t done JavaScript for years but isn’t JavaScript a
bit more of a higher level language, which would make a developer more
productive?

Rust being closer to the hardware should require more code, and effort, to
accomplish the same task.

~~~
echelon
> isn’t JavaScript a bit more of a higher level language

Rust has zero-cost abstractions that feel like using Ruby and a rich type
system that makes it incredibly expressive. Working in other languages feels
like going back to assembly.

I wouldn't want to design state machines in any other language. Rust's enums
make it feel smooth as butter. They're a killer app. (The whole ecosystem is.
Cargo. Package naming. Traits. So much good stuff.)

Rust is my most productive language now, and I work in Python, Java, and
Typescript codebases frequently.

Edit: I'm being downvoted for expressing preference? What's with all the Rust
hate? Learn it instead of being a hater. It's a wonderful tool, and it's silly
to dismiss because you think people are being hipsters or something. There's a
reason people love it.

~~~
zenhack
I think a lot of the best the best things in Rust don't really have anything
to do with low level programming per-se. And I find that for most
applications, even with all of the extra goodness, the lack of a GC totally
craters productivity. Its not because I'm fighting the borrow checker -- I got
the hang of it pretty quick. But it means that every API is complicated by the
need to think about lifetimes and ownership, having to think about different
types of smart pointer, etc. It means you have to manage all of these silly
little details which for most applications are pretty irrelevant.

This isn't a criticism of Rust; it's specifically designed for applications
where those things _do_ matter. But for the overwhelming majority of apps they
don't, and I'd reach for a different tool.

I've found that once I get into a rhythm and I've been working on something in
Rust for a bit, it doesn't feel that hard to deal with all that. And a few
times I've thought to myself "hey maybe the GC isn't actually buying you all
that much?" But then I go back to a GC'd language and watch just how much
faster stuff gets done. It's not even close. I think it's one of these things
where your brain doesn't notice the time that goes by when you're doing what
is essentially mindless busywork.

Part of this is also having come from doing a fair bit of stuff in Haskell,
Elm, and a bit of OCaml; the best "high-level" language features are inspired
by that language family (including enums) and so it feels like a better
control for the difference a GC makes vs. js and friends. It makes a big
difference.

~~~
blub
What's puzzling is why a language designed for memory safety and low-level
control and performance is even being considered for web development where
they had the former all along and they generally don't care about the latter.
Or if they do they use Java, Go or throw a couple dozen more servers at the
problem.

~~~
imtringued
With Java you only need to throw more RAM at the server. The performance is
perfectly acceptable compared to something like Python or Ruby. You can always
squeeze out more performance with Rust but the primary benefit is the lack of
a GC.

~~~
sweeneyrod
I don't understand your last sentence. What benefits does lack of a GC have
other than more performance?

------
harikb
Alon Zakai[1] gave a good talk[2] on the current state of WebAssembly,
particularly on the current state of performance

1\. [https://twitter.com/kripken](https://twitter.com/kripken)

2\. [https://youtu.be/4ZMY3QE5t9o](https://youtu.be/4ZMY3QE5t9o)

~~~
apatheticonion
I'm not certain exactly how LLVM works so I am not sure this is the right
question to ask but - How does Web Assembly relate/compare to LLVM? Does LLVM
solve the problem of a single binary that can be run portably?

~~~
harikb
There are not comparable afaik. WASM is also more ambitious, along with WASI
(system interface) creating a portable final executable (compare to JVM),
whereas LLVM is only a set of intermediate language and tools.

When this transition period goes away, LLVM should hopefully compile to WASM
binary as a target. The current path described in the video of WASM -> C ->
clang -> llvm -> native-binary is a temporary workaround afaik.

~~~
jfkebwjsbx
WASM isn't "more ambitious". It is a spec for portable bytecode, nothing more,
nothing less.

LLVM is one of the best toolchains for many languages.

They are completely different things.

~~~
harikb
Yes, I agree. Wording wasn't right. What I meant was that it is trying to
define a universal target with runtime system interface and such. The only
reason I drew a comparison was that both are trying to bring standardization,
but in different contexts.

------
Longwelwind
I spent the last 2 years making an online adaptation of a board game. I chose
Typescript mainly because I was comfortable enough in this language and I
don't regret this choice.

Typescript is, for me, the right balance between the strictness required to
manage a mid-size codebase, and the looseness necessary to be productive (I
definitely don't want to manage low-level things like memory when coding the
gameplay of the board game).

On top of that, if your project is open-source, using JS/TS makes it more
likely that someone can contribute to the project, compared to Rust, which has
a higher learning curve.

Being able to easily share code between the client and the server is a big
bonus too. The article points that with WebAssembly, it's possible to do it
with any language, but I'm not sure it's stable enough to be used yet.

I'm thinking of making a library similar to boardgame.io (because I think
there are some parts that could be done better), and I'll most probably keep
Typescript for it.

Curious to see how using Rust for this will play out!

------
v_pragma
Keep in mind that WebAssembly is not a silver bullet for performance, and
carefully crafted JS application (written in engine-friendly way) will perform
roughly the same or even better than its WA equivalent. I've rewritten chunk
of my math-intensive app in AssemblyScript half a year ago - it took me about
a month to fight through all the compiler bugs, I used every optimization
possible (used floats everywhere, disabled array boundary checks, disabled GC
for 70% of classes) and still end up with a binary that is 30% slower than the
original JS code. It was mostly AssemblyScript's GC, which was extremely slow
(and probably still is), and with GC completely disabled (which is an unfair
advantage for WA) performance was almost the same.

~~~
maxgraey
That's pretty interesting. Could you share you project?

There are benchmark which compare JavaScript and AssemblyScript:
[https://github.com/nischayv/as-benchmarks](https://github.com/nischayv/as-
benchmarks) [https://github.com/nischayv/as-
benchmarks/issues/3#issuecomm...](https://github.com/nischayv/as-
benchmarks/issues/3#issuecomment-623159721)

~~~
benjamin-lee
I'm not the OP but I can confirm in my own project, we found about a 10x
performance gap between AssemblyScript and TypeScript. In essence, we're
working on a rewrite of DNAVisualization.org[1][2], a serverless web tool for
the interactive inspection of raw DNA sequences. We hoped that WASM would give
us a performance boost but have been generally disappointed with both the
performance and the amount of complexity involved in getting the tooling to
work.

We did do a benchmark[3] and, unless we made an error (likely, given that all
of us are new to WASM), found that JS was much faster for our simple
algorithms. WASM had the approximate performance of our original pure Python
implementation[4], so not great.

[1]: [https://dnavisualization.org](https://dnavisualization.org) [2]:
[https://academic.oup.com/nar/article/47/W1/W20/5512090](https://academic.oup.com/nar/article/47/W1/W20/5512090)
[3]:
[https://github.com/Lab41/dnaviz/tree/benchmarks/benchmarks/a...](https://github.com/Lab41/dnaviz/tree/benchmarks/benchmarks/a..).
[4]: [https://github.com/Lab41/squiggle](https://github.com/Lab41/squiggle)

~~~
maxgraey
I made PR which suggest some changes and fixes:
[https://github.com/Lab41/dnaviz/pull/21](https://github.com/Lab41/dnaviz/pull/21)

~~~
maxgraey
As you can see AssemblyScript approx 4x-4.5x times faster now

------
rkwz
> Webassembly Is Faster Than Javascript

Just curious, how's the OP measuring this? Also, would be very interested in
the stack - is OP using Yew/Seed/etc or server rendered pages with Rust?

~~~
nicolodavis
I'm just using an SPA written in Svelte on the frontend. I only use Rust for
the game state updates.

About measurements, I just whipped up a quick benchmark comparing the
JavaScript state updates with the WASM version. You do pay a cost crossing the
JS / WASM boundary, but the WASM version is faster overall for my application.
I'm not particularly concerned with performance at the moment (it was just a
nice to have).

------
Asooka
One thing articles like this always miss, and what I'm most keen on, is how
exactly the bridging works. Is there a standard Rust wasm crate that exposes
the DOM? Do you pass some struct with function pointers? Is the Rust code
exposed as a black box with no connection to the outside world and you just
call a few entrypoint functions? Can you call Rust from JS and JS from Rust?
If you go JS->Rust->JS->Rust->JS and the innermost JS function throws an
exception, is all that properly propagated up the stack?

~~~
steveklabnik
There are two low-level bridges: js-sys provides bindings to all the
ECMAScript stuff, and web-sys provides bindings to all of the rest of a
browser environment, including the DOM.

> Can you call Rust from JS and JS from Rust?

Yes.

I personally have written some JS code that returns a promise, wrapped in wasm
that turned it into a Rust Future, then converted that Future into a promise
that I've returned to Javascript.

> If you go JS->Rust->JS->Rust->JS and the innermost JS function throws an
> exception, is all that properly propagated up the stack?

Sort of. Rust doesn't use exceptions, but the binding converts a JavaScript
exception to a Rust "result" type and vice versa at the boundary, so if you
propogate it, it will get properly propagated.

------
loxs
I will only nitpick on the part about TypeScript not being type-safe enough,
where extra fields are possible or wrong types can be sent over the wire.

io-ts [0] completely solves this issue, to the point where I don't think it's
less type-safe than Rust in any practical manner. I've been writing apps in TS
this way for the past year and I have quite a large codebase in production.
The errors you mention do not happen.

[0] - [https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)

~~~
beaker52
I love things like this, but at the same time when I look at the API this
library provides, it's not junior-friendly.

Even though I acknowledge it solves some problems I'd like to solve, if I put
code using this library infront of a junior developer, they'd be paralaysed,
and at best, if they weren't, write code with it that another junior wouldn't
understand. That makes it difficult for me to justify introducing it.

~~~
loxs
I agree in principle, though in this particular case io-ts does not tend to
produce incomprehensible code. Maybe if juniors use it, it would, but it's
easy to encapsulate the IO codecs in their own modules where the functional
style of io-ts/fp-ts does not leak out to other parts of the code and only
types can get reused.

------
truth_seeker
In general, I think the significant improvement in Speed in case of
WebAssembly binaries will be largely due to SIMD support. But performance gap
between JS and WebAssembly is not at all deciding factor unless you are
creating a high quality Games. There are lot of online games with low to
medium graphics quality created using 2D canvas or 2D/3D WebGL libraries which
run just fine on modern web browsers.

Most developers, at least in my experience see just plain Array and JSON. If
they get themselves familiar with API like WeakRef (WeakSet/WeakMap),
ArrayBuffer along with DataView and Various Typed Arrays (Int8, Int16, Int32,
Uint8,Uint16,Uint32, Uint8Clamped and likewise for Float and BigInt) they can
write Garbage heap friendly and more computation focused code.

Besides that, strictly speaking for standard web application development, JS
ecosystem of libraries and frameworks are miles ahead for handling various
kinds of UX/UI journey scenarios. Developer tools in the browser to do various
kinds of performance inspection and profiling of the JS code.

I wonder why JS engines (like V8 for example) rely highly on Scalar
instructions ? There is lot of scope to apply auto-vectorization and generate
SSE, AVX, NEON (for ARM) instructions. If they implement this or at least
provide some API like SIMD.js (one they abandoned in the past), it will make
WebAssembly close to redundant unless you hate JS or other PLs which
transpiles to JS.

------
magicmouse
Rust is extremely poor for web apps and graphical interactive software in
general. Having been using Beads (a competitor to typescript) for the last few
months, i couldn't possibly build my food ordering app quickly in Rust. There
are hundreds of art assets to manage, and every screen has to automatically
re-flow depending on the resolution of the device. Without a concept of DPI
and the ability to measure text, and have a layout system, all of which is
built into the Beads language, it would require a very tedious programming
effort. Most of the time coding a graphical interactive product is making it
look nice on all the different sized screens; Rust does nothing for this very
time consuming task.

Typescript may force you to use the awful CSS, but having some layout system
is better than none. And we could also talk about event management, and sync
between client and server, none of which Rust is particularly good at.

------
ralmidani
As someone who has (mostly) enjoyed working with Python and JS (CoffeeScript
in the past, and ES6+ and TypeScript more recently), and also dabbled in
Ruby/Rails, I've been intrigued by Rust for a while. Its promise of being
close in speed to C/C++, but safer and more ergonomic, sounds great. I have
not attempted to build anything with it yet, but I've looked at what (I think)
is enough examples to be familiar with its constructs, and have seen some
benchmarks.

For systems software or libraries that are meant to be hooked into from, say,
a JS/TypeScript environment (see [https://deno.land](https://deno.land), a
promising alternative to Node), it seems like Rust has a lot of potential.

But for building applications (which is what I'm focused on currently) it
seems Rust has a "No OOP for you!" attitude that gets in the way of modeling
your application domain quickly. Yes, you can use impl and trait as an
alternative to classes. But it seems like you have to jump through a lot of
hoops; define your structs, define a trait for default behavior and remember
that &self is provided as an implicit first argument to the methods (this is
similarly cumbersome in Python), then define an impl for each corresponding
struct (don't forget about &self!). As opposed to just declaring a base class
and overriding when you need to in the subclasses. I am definitely not saying
classes are the only way to do OOP, but at least give developers the option of
using them.

I have found Swift attractive for application development because it gives you
structs for one-off (value-based) data types, classes when you need an easy
way to do inheritance and polymorphism (and/or need reference-based data
types), and extensions as a more abstract way to enhance structs and/or
classes (and/or enums). It doesn't force you to use classes (and the community
appears to think protocols are a better construct), but the language remains
approachable, and you can always start with classes then refactor to protocols
when the need arises.

~~~
deltron3030
Is Vapor the rails-like go to web framework for Swift? Is it viable for indie
hackers, or is it more like Java geared towards the enterprise? I find Swift
interesting as a language because it seems that it's well balanced, usable for
low level systems programming and higher level applications. But protocol
first kinda indicates big design up front, something more geared towards
enterprise usecases..

~~~
ralmidani
I don't have any statistics, but based on the amount of learning articles,
books, etc. out there it seems like Vapor is the dominant Swift Web framework.
Kitura looked promising, but IBM has stopped supporting it, so its future is
not clear (the last commit to the main branch was in November 2019). Also, the
two main Vapor devs are members of the Swift Server Work Group (with the other
two being from Apple): [https://swift.org/server/](https://swift.org/server/)

I'm not sure how to answer your question regarding whether Vapor is viable for
indie hackers, because I've only been skimming the docs and looking at small
examples. But it seems to draw a lot of inspiration from Express.js and/or
Ruby's Sinatra library. It doesn't seem to have the up-front complexity of
something like Java's Spring Framework, although I understand you can use
services and dependency injection if needed. So my first impression is it's
easy to get started, but it enables you to refactor to something more complex
if your application demands it.

~~~
deltron3030
Thanks for your answer. So Vapor for building APIs, not web monoliths, good to
know. It kinda makes sense considering that most of the users will use mobile
apps on the client side.

Personally I also find Elixir and the Phoenix framework very interesting.

~~~
ralmidani
No problem! Vapor does have its own template system if you don't want to build
"just" an API: [https://github.com/vapor/leaf](https://github.com/vapor/leaf)

I have also looked at Elixir and Phoenix, but have not written any code in
them. I have yet to really dive into anything outside the C-like languages
(Python, JS, Java, Swift, Ruby, C, C++), and Elixir seems like a good reason
to venture outside my comfort zone.

By the way, no pressure, but if you ever want to discuss Swift, maybe do some
paired programming/studying, let me know. I'm still fairly new but I have
experimented with building a Swift-to-CSS DSL that I would like to eventually
spend more time on. If you want to email me, ragheed.almidani is the name, and
protonmail.com is the domain.

------
nailer
> For example, the data might contain additional fields or even incorrect
> values for declared types.

I understand 'incorrect values' (this is true, see
[https://github.com/Microsoft/TypeScript/issues/15480](https://github.com/Microsoft/TypeScript/issues/15480))
.

But TypeScript definitely doesn't like adding additional fields. Right now I'm
working on TypeScript, added the new Fastify raw body plugin, and forgot to
extend our custom Request type. The error is:

    
    
      Property 'rawBody' does not exist on type 'CustomRequest<DefaultQuery, DefaultParams, DefaultHeaders, any>'.ts(2339)
    

Ie, we can't just add a field.

Appreciate I may be wrong, or we have different definitions here, but I'd like
to discuss.

~~~
nicolodavis
Something like this is valid TypeScript I think?

    
    
      interface MyType {
          a: number;
      }
    
      function process(value: MyType) {
          console.log(value);
      }
    
      const value = { a: 1, b: 2 };
    
      process(value);

------
blacksoil
> However, it [Typescript] does not actually ensure that the data you are
> manipulating corresponds to the type that you have declared to represent it.
> For example, the data might contain additional fields or even incorrect
> values for declared types.

This made me curious, as it sounds like something that can be added as a
transpiler option under tsconfig.json. But it turns out Typescript doesn't
already have a support for "nominal" type, but there are some tricks one can
leverage to achieve similar thing:

[https://medium.com/better-programming/nominal-typescript-
eee...](https://medium.com/better-programming/nominal-typescript-eee36e9432d2)

------
_bxg1
Does anyone know the progress on exposing browser APIs (and hopefully real JS
objects) to WASM directly? I think its use-cases will remain pretty narrow
until then, but I haven't heard much noise about those developments lately.

------
ronanyeah
I replaced Node.js with Rust ages ago.

It was a brutal learning curve but having the compiler cover everything I do
is a massive advantage that never stops paying dividends.

------
wdb
I am actually converting a work project from TypeScript to Swift as it makes
the writing of code more fun and then just leverage either for the backend
application or as part of web application via WebAssembly. Main reason it's
easy to share the code with different targets (win32, arm, WebAssembly, osx)
so its highly reusable. And I like Swift more as a language compared to Rust

Really enjoying it so far.

------
Accacin
Completely off topic, but I'm a front end developer who dabbles with a range
of languages and also enjoys trying out new languages, but I've never really
used a 'back-end' language and I've been trying to find one that works for me.
What do people recommend nowadays? (Only asking as I've seen people talking
about Rails/PHP/Node, etc.).

------
danbruder
Rust's type safety and error handling are helpful tools to have in your belt
when gluing together the pieces needed for a web api. I have been working on a
new product at my day job that has needed to change a lot as we learn and grow
and I am happy with how Rust has been reliable in the face of that change.

------
k__
Good idea.

TypeScript is too Java/C# for my taste. Rust feels more OCaml-ish.

It has more predictable performance than JavaScript and often it can be
better.

If Rust gets a bit more ergonomic (via language or crates) it could be a good
alternative and finally save us from the horrors of
Electron/Slack/Bitbucket/etc.

------
kp25
I would like to get started with Rust & Game Development. Any resources for
that?

~~~
rlp
[https://arewegameyet.rs/](https://arewegameyet.rs/)

Rust is not really there yet for game development, in my opinion. Amethyst is
probably the most advanced 3D engine at the moment, but they are having some
issues with picking an ECS implementation, and it's still very young.

There are a few 2D engines, but they are also not particularly mature either.
Coffee looks interesting, although I haven't tried it.

For something lower-level, there's gfx.rs (Amethyst uses this), which is quite
impressive. gfx-hal is quite nice for abstracting over
DirectX/Vulkan/OpenGL/Metal/etc.

------
asdf-asdf-asdf
i'm glad it worked for the author, and i am sure you can achieve better
performance with Rust than with NodeJS, but i'd like to discuss some of the
mentioned advantages:

in general, typescript is optimized for cooperating with other javascript
code, to make it easy to drop it into a javascript-based project, and also, it
does not really have it's own "runtime". typescript is javascript plus types.
in fact, if you want to convert from typescript to javascript, you can take a
typescript-file, and just delete all the type-definitions and you get a
working javascript file (there are some exceptions to this, but it generally
is true). this approach has it's downsides of course, for example,when you
need to interface with a javascript (not typescript) module, you can easily,
but you have to know what types it expects and returns,otherwise you might get
invalid structures in your code. there are things that can help you there
([https://github.com/DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)),
and it works quite well in practice, but there is no 100% guarantee that the
types will be correct.

>> STRICT TYPING (in typescript) For example, the data might contain
additional fields or even incorrect values for declared types.

\- typescript is structurally typed most of time, so if you have a function
that needs an `{a:string, b:string}`, and you send it an `{a:string, b:string,
c:string}`, it will accept it. it's a different trade off,sometimes better,
sometimes worse, compared to nominal-typing
([https://en.wikipedia.org/wiki/Nominal_type_system](https://en.wikipedia.org/wiki/Nominal_type_system)).

\- the part "even incorrect values", it should not happen in your own code. as
i wrote above, i can imagine it happening when interfacing with other non-
typescript code.

>> DATA VALIDATION: You have to write data validation code to ensure that
you’re operating on correct data in TypeScript. You get this for free in
Rust...

in typescript if you want to read,let's say JSON data,and map it to a
typescript-structure, and return an error if it does not have the correct
structure, you can use libraries like IO-TS ([https://github.com/gcanti/io-
ts/blob/master/index.md](https://github.com/gcanti/io-
ts/blob/master/index.md)) to make that happen. i do not know how you get this
"for free" in Rust, i know there are libraries like Serde
([https://serde.rs/](https://serde.rs/)) that do it.

------
eddhead
The gist of this article applies to switching from JS/TS to Uno/Blazor as well
as they both support WebAssembly just as well, and they both get robust UI
frameworks as a bonus.

------
maerF0x0
@nicolodavis I would love to hear your thoughts and reasoning for not using go
+ wasm compile target? Not as a critique but to understand your point of view.

~~~
nicolodavis
No reason except that I've written Go in the past and wanted to learn a new
language :)

Comparing the two languages, I would say that Rust's enums and pattern
matching make it easier to work with for my specific use case.

------
qaq
I like Rust but I would much rather use Swift for something like that
especially if SwiftUI like thing was part of the deal.

~~~
nicolodavis
Note that Rust is only used for the state updates. All the UI stuff is
TypeScript (using Svelte).

------
franklampard
> For example, the data might contain additional fields or even incorrect
> values for declared types.

Can you give an example?

------
pjmlp
I guess AssemblyScript would have been a better option, given it being a
language subset for WebAssembly.

~~~
wtetzner
Except that doesn't address any of the other reasons they preferred Rust...

------
anyfoo
As long as you use a language with a good, static type system, I don't care so
much what you use. TypeScript or Rust, for all I care you can transpile
Haskell into JavaScript if you feel adventurous. But don't use a dynamically
typed language as the source language for anything that is supposed to be more
than a simple script.

~~~
hombre_fatal
> But don't use

This is just cargo-culting static typing: "If I avoid dynamic typing at all
cost, the cargo crates will surely rain on down!"

You'll find that picking a language is more of a business decision than the
sort of technical static-vs-dynamic checkbox test you might use to pick the
language of your next weekendware.

This kind of absolutist rule of thumb is more flame bait than morsel of
wisdom.

~~~
lmm
This is the fallacy of the grey. Yes, there are nuances and special
circumstances, but the overwhelming majority of the time, static typing is
simply better. That's one of a small handful of clear consensuses from the
last 20-30 years of programming language evolution.

~~~
hombre_fatal
It's not any better if business trade-offs make another decision better. You
don't have "all things equal" trade-offs in the real world.

Want an easy concrete example? You and your cofounder have 10 years of Ruby
experience and investors/customers who want a product yesterday. Or the
deliverable that makes most sense is a PHP script that users can drag into
CPanel because that's your customer base.

The tinkerer inside you always wants to try new things and convince you that
some greener tech on the other side of the fence are going to make the
difference. It's usually just procrastination from the actual hard stuff:
building things people want, today.

~~~
lmm
> Want an easy concrete example? You and your cofounder have 10 years of Ruby
> experience and investors/customers who want a product yesterday. Or the
> deliverable that makes most sense is a PHP script that users can drag into
> CPanel because that's your customer base.

True but facile. Sure, for every imaginable technology, there is a conceivable
scenario in which that technology is the right choice. Doesn't mean there's no
such thing as a good or bad technology.

> The tinkerer inside you always wants to try new things and convince you that
> some greener tech on the other side of the fence are going to make the
> difference. It's usually just procrastination from the actual hard stuff:
> building things people want, today.

That's actually an argument for being more absolutist about the technical
side: you're unlikely to be in the obscure circumstances where a dynamic
language would actually be helpful, and even more unlikely to have that be
more important than your business decision. So rather than carefully
considering your circumstances and weighing up the tradeoffs, it's better to
follow the consensus for what's a good general-purpose language (which these
days means a statically typed language) and get on with building your
business.

------
RyanGoosling
If you push Rust to client-side WASM, can it still perform DOM manipulations?

~~~
steveklabnik
Yes. It has to call out to JS to do so. It's implemented in a way that's
forwards-compatible so once wasm can do so natively, your code will just
magically get faster.

~~~
nicolodavis
That's right. For my use-case I decided to just stick with JS for UI stuff
(using Svelte). I call into Rust code like a black box to update some state.

------
chickenpotpie
A little disappointed not to see
[https://www.assemblyscript.org/](https://www.assemblyscript.org/) included in
the discussion. Especially since it removes the "JavaScript is slower than
WASM" argument.

~~~
titzer
I'm not quite sure what you mean here, because AssemblyScript compiles to
WASM, not JS.

~~~
iCarrot
I guess the argument was that you can write in JS (well, something that is
close to TypeScript which is close to JS anyway) and compile to WASM,
therefore the speed argument becomes invalid.

------
AzzieElbab
That is quite a move. Like moving from USSR to USA.

------
Joshi323
No substantial arguments in the article. Hackernews used to be one of the rare
places where quality is valued. How can such a low content and low quality
article get so high on the HN frontpage?

