Background: I learned Javascript 1997 and kept up.

I have extensive experience in ES6/React for the browser and Java/Kotlin for Server-, Desktop- and Mobile-Apps.

A week ago I switched a fairly new project from the usual setup (react/babel/webpack) to Kotlin-code only. My IDE compiles the Kotlin to JS now and webpack serves it as usual.

Writing the react-bindings took me an hour, after that my productivity went up by about 10.000%. It's finally on par with my productivity on server and desktop. No type errors, fast refactoring, no "undefined" errors and all the goodies (extensions) of Kotlin.

Removing the complex eslint settings and babel-setup from webpack and package.json felt triumphant.

My JSX looks like this now and is completely typesafe:

    val LieferungenList: (props: ListProps) -> ReactElement = {
        Datagrid {
            div {
                className = "..."
                ...        
            }
            TextField {
                source = "date"
            }
            TextField {
                source = "produktname"
            }
            EditButton {
            }
        }
    }
I even get compiler-errors when I nest HTML-tags the wrong way (h1 inside h1) or so.

I couldn't be happier. I'll never touch plain ES6 again.

What advantages does this have over Typescript? The ecosystem and mindshare are overwhelmingly in TS' favor I would imagine.

For compile-to-js languages it seems most attractive to those that use the host language (Clojure, Scala, Kotlin, Haskell, etc.), whereas for would be js expats, Typescript seems like the natural choice given current trends.

I think for a compile-to-js language (vs. a transpiler like Typescript) to take off it's going to need at least:

  Tiny generated binaries
  Great js interop
  Large ecosystem
  Seamless cross compilation (e.g. JVM/JS)
  Fast compiler
Reason + Bucklescript is the only combination I know of that could potentially pull off the above, blazing fast compilation and miniscule binaries being its greatest strengths at the moment.

Typescript still has some issues that only a "real" strongly typed language can fix. The biggest one is related to third party JS/TS libraries. If the object was 'any' at some point, if you make an invalid cast Typescript will trust you. If it's a union type, typically (Obj | undefined), everything will work fine until one day the object is undefined and everything blows up. You won't know because everywhere in your code the object can never be undefined.

Essentially Typescript Is too trusting. In Java or similar languages, if something comes in as Object you know all bets are off. If you cast and it succeeds you know 100% what kind of object it is. In Typescript it's possible for the type to look fine but be completely wrong, or worse, wrong in a subtle way. And there's no way to fix this without breaking interop with JavaScript.

Since Java has always been strongly typed and has a ton of libraries available this isn't an issue in Kotlin.

Java/Kotlin are just far better designed languages and no amount of banging on JS is going to make it as well designed. Look at PHP, after 10+ years of trying to make it reasonable it's only "okay", there's too much baggage.

The bytecode for Java/C# is much more compact than JS, the runtime is about 10x faster, they have far better standard libraries. They will compile down easily to wasm since their VM's essentially already compile down to native machine code on whatever platform they run on. It's as easy as adding a "wasm" machine target to their runtime and porting the garbage collectors.

I fully expect Wasm to wipe out front end development as we know it. Java and C# are far better suited for what the web has become, essentially an application platform. We've seen the future already, just 10 years too early, in Java applets.

> If the object was 'any' at some point, if you make an invalid cast Typescript will trust you.

I believe any language that supports "any" allows this. Doesn't Kotlin? https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/

> If it's a union type, typically (Obj | undefined), everything will work fine until one day the object is undefined and everything blows up.

Not if you set strict: true in your typescript options, or you can separately enable just strictNullChecks

> Essentially Typescript Is too trusting. In Java or similar languages, if something comes in as Object you know all bets are off. If you cast and it succeeds you know 100% what kind of object it is. In Typescript it's possible for the type to look fine but be completely wrong, or worse, wrong in a subtle way. And there's no way to fix this without breaking interop with JavaScript.

Instead of casts that fail, typically you would use type guards to deal with this. That way you can isolate unsafe casting code to a single place.

> Since Java has always been strongly typed and has a ton of libraries available this isn't an issue in Kotlin.

DefinitelyTyped (http://definitelytyped.org/) has types for over 3500 popular libraries: https://www.npmjs.com/~types

> the runtime is about 10x faster.

Hmm. I see 1.5x-6x here, with average around 3-4x: https://benchmarksgame.alioth.debian.org/u64q/compare.php?la...

> I believe any language that supports "any" allows this. Doesn't Kotlin? https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/

Kotlin's Any is pretty much the opposite of TypeScript's any. In TS it disables type checking completely (according to the docs). In Kotlin it's the top type (similar to Java's Object type), which anything conforms with, but doesn't expose any operations at all (except for the stuff that the JVM provides for free).

The closest match to TS' any would probably be C#'s dynamic https://docs.microsoft.com/en-us/dotnet/csharp/programming-g....

Yes, this is the effective difference between Typescript and typecasting in most other languages. Typescript, since it compiled to js, doesn't know the runtime type so it can't use reflection to make sure casts are valid. It just takes your word for it. If the cast isn't always correct prepare for a world of pain trying to track it down instead of getting an exception on casting failure

I encountered this the other day, while playing with typescript for the first time. Is there a good solution, such as a utility function that does a runtime check before casting? I suppose I could write one for each type cast, but it seems like I shouldn't need to.

Yes, a runtime check in TypeScript is the same as a runtime check in JavaScript.

    function inc(n) {
      if (typeof n === 'number') { return n + 1 }
      throw new Error('Parameter n is not a number');
    }
If you wanted to actually runtime check all types (probably not advised) you could parse the type annotations.

Or you could define your types using something like JSON Schema and validate against that.

https://github.com/bcherny/json-schema-to-typescript

https://github.com/YousefED/typescript-json-schema