
TypeScript support in Electron - Garbage
https://electron.atom.io/blog/2017/06/01/typescript
======
habitue
Flowtype is seeming more and more like the Mercurial to Typescript's git.

(That is, in terms of inertia, it seems like the community has decided on a
winner)

~~~
boubiyeah
And for good reasons.

flow started as "the better one of the two in theory" with better ideas, more
strictness, way more expresiveness in its type system. But typescript took all
these ideas, listened to the community and bridged the gap in features really
fast, together with more stability, thus making flow pretty much obsolete.

typescript is way more stable. I can take a nightly or RC version of
typescript and I know it's going to work better than flow which I tried
several times and always let me down. If you don't trust a type system, it's
hard to justify using it at all, apart from the documentation it provides to
other devs.

These projects are complex, and I think only the typescript team invested
enough to make it truly work.

~~~
bad_user
> _If you don 't trust a type system, it's hard to justify using it at all,
> apart from the documentation it provides to other devs._

100% agree, although I have to wonder, why don't you see that Typescript is
NOT a type system you can depend on.

Fact of the matter is that Typescript has serious soundness issues and will
always have. Those problems haven't disappeared.

What this translates to in practice is that Typescript annotations are little
more than documentation. And it simply doesn't compare with any sane static
language where the first line of defense is the compiler.

~~~
resf
What is the practical benefit of soundness? I offer that soundness is a
disease that makes programming languages far more complex than they have any
right to be.

A static type system exists to prevent _some_ classes of bugs and enable code
completion.

However whenever "soundness" becomes a design goal, it enevitably usurps
everything else (because it is an objective binary goal) and leads to
languages that cease to value other things like simplicity or directness.

A type system can never catch _all_ bugs and reliable programs ultimately
depend on a human being understanding and verifying the code. The most
important goal - if you value reliable programs - is that the code is
intelligible to people.

~~~
bad_user
Reading from the comments here, I believe that people don't realize how bad
the unsoundness is in Typescript:

    
    
        class Dog { name: String }
        class Engine { name: String }
    
        function start(ref: Engine) {
          if (!(ref instanceof Engine)) 
            throw Error("oops")
        }
    
        // Typescript does not complain
        start(new Dog())
    

This sample is due to Typescript doing "structural typing". According to its
rules, if Engine and Dog both have the "name" property, then they must have
the same behaviour as well. This is also inconsistent with the behaviour of
classes in Javascript (e.g. see the behaviour of `instanceof`).

The biggest problem is that generics are what they call "bivariant", which is
lingo for "completely fucked up". Here's a classic gotcha that caught people
by surprise with Java's array since forever:

    
    
        class Animal { isAnimal: Boolean = true }
        class Dog extends Animal { isDog: Boolean = true}
        class Cat extends Animal { isCat: Boolean = true }
    
        const dogs: Dog[] = [ new Dog() ]
        const animals: Animal[] = dogs
        animals.push(new Cat)
    
        for (const dog of dogs) console.log(dog.isDog)
        //=> true
        //=> undefined
    

Well, it's unfair to pick on this, since they give a similar example in their
own documentation, right? But this extends to inheritance as well, because
input parameters in functions are not contravariant in Typescript:

    
    
        abstract class FlatMap<A> {
          abstract flatMap<B>(f: (a:A) => FlatMap<B>): FlatMap<B>
        }
    
        class Box<A> extends FlatMap<A> {
          flatMap<B>(f: (a: A) => Box<B>): Box<B> {
            throw new Error("Not implemented!")
          }
        }
    

It should be obvious to everybody why this is wrong:

    
    
        class AnotherBox<A> extends FlatMap<A> { ... }
    
        const box: FlatMap<number> = new Box<number>()
        box.flatMap(x => new AnotherBox<number>())
    

In case you're wondering, that interface is the beginning of the Monad pattern
and the problem here is that monads are incompatible with each other. So in
order to compose instances together, you do rely on the compiler to protect
you. Think Promises being combined with Arrays, both of which are monadic
types. Not going to work, is it?

In less expressive static language lacking higher kinded types, which you need
to express such interfaces, there's a current trick that people do to work
around it: [https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-
ki...](https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-
polymorphism.pdf) ; This has been used in Elm and it's being used in Kotlin as
well, see for example:
[https://github.com/FineCinnamon/Katz](https://github.com/FineCinnamon/Katz)

But Typescript is on a whole new level of wrong, because you can't trust the
compiler for correctness, so you can't trust it for protection, at all. You
see, this is not pie in the sky academics, but actual code that can happen in
your app, mistakes that the compiler should have prevented you from making. In
the above case Typescript really is just documentation and just like
documentation in many cases, it can be _wrong_ documentation. To make this
even more frustrating, Microsoft's other language, C#, does not have the
problems that I enumerated.

And I know what people say - oh, this is still useful. Well, guess what,
writing JSDoc + having Google Closure to validate is actually more useful,
while not being non-standard ;-)

~~~
bcherny
You're treating this specific case as a fundamental issue, when it's a
specific and superficial one that can be reasonably addressed in a future TS
release:

See for example:

\- Nominal types proposal
[https://github.com/Microsoft/TypeScript/issues/202](https://github.com/Microsoft/TypeScript/issues/202)

\- Co/contravariance annotations proposal
[https://github.com/Microsoft/TypeScript/issues/10717](https://github.com/Microsoft/TypeScript/issues/10717)

~~~
bad_user
These choices are fundamental to the language as it was designed. There's
nothing more fundamental than how variance works.

Want to bet that in 2 years from now we are still going to talk about the same
language with the same issues, and that those two proposals are going to be
rejected?

~~~
bcherny
I'm not sure I understand why you think that. TypeScript explicitly prefers
real world usability to theoretical soundness, so if the community is vocal
about the need for these features, I don't see why TS would turn them down.

~~~
bad_user
> _real world usability to theoretical soundness_

The soundness we are talking about in this case isn't theoretical at all and
in fact such an argument is anti-intellectual. This is anti-intellectualism.

As for the "community", we are talking about one where the majority has never
worked in sane static languages.

~~~
bcherny
You are misunderstanding what I said.

Either one of the 2 issues I linked would fix the specific problems you
outlined. You don't need a globally sound type system, H-M inference, or
anything like that to fix those specific problems; local inference and opt-in
nominal typing would work just as well.

Having used TS daily for a few years, I can vouch that your cases are
pathological, and don't come up in practice often, if at all.

------
mohamedmansour
Best thing I done in my spare time 5 years ago was converting the entire
JavaScript code base in Bing to TypeScript, that improved agility 10000x

------
dgreensp
Resources for getting started with Electron+TypeScript are still not great,
contrary to the tone of this article. I'm working on getting electron-compile
up and running, and I currently have compilation but no type-checking. I don't
expect it will be too hard to figure out, but it's not a five-minute task
where you just start with a repo or follow a tutorial. There are various
quick-start repos but they appear old. Someone let me know if I'm looking in
the wrong place. This article and the accompanying video talk exclusively
about the experience of editing code, not compiling it.

~~~
sillysaurus3
It looks like there's a walkthrough video here, where they successfully get
TypeScript working with Electron:
[https://youtu.be/PJRag0rYQt8?t=455](https://youtu.be/PJRag0rYQt8?t=455)

------
cies
Next up: BuckleScript/ReasonML support :)

~~~
ch4s3
It would be cool to see a lot of the Electron app crowd taking up ReasonML. I
like BuckleScript, but I think Reason might be easier to teach to JS devs. I'd
love to replace my react frontend with ReasonML.

~~~
akhilcacharya
I think what OP means is Reason compiled via JS.

~~~
cies
Yeah. BS bindings for OCaml-to-JS interop. Then using the Reason tools, as
they provide a really nice workflow.

------
nahtnam
Anyone know what editor and theme they used in the screenshots? It looks like
VS Code.

~~~
MaxArt2501
It's definitely VS Code and it's quite mind-blowing thinking that they're the
guys behind Atom, and the blog's domain is electron.atom.io.

~~~
jamesgeck0
Atom doesn't have built-in support for TypeScript annotations. I've gotten the
impression that VSCode is somewhat more popular with the TypeScript crowd.

~~~
glitcher
Since MS develops TypeScript they have a big advantage in making TypeScript a
first class citizen in VSCode. I see many developers who would prefer a
different IDE normally, but decide on VSCode because it seems to be ahead of
everyone else on TypeScript currently.

~~~
whatever_dude
Not sure that applies like that. Typescript support is based on the Typescript
language server, which uses their open source language server protocol, which
is open for other editors to use (and indeed adopted by a bunch of them). So
in theory other IDEs could support TS with the same level of VSC as long as
they adopted the protocol, without the need for discussion TS functionality.

------
supernintendo
This is exactly what I've been looking for! The only available type
definitions for Electron I could find (up until now) were outdated. I'll be
making good use of this. Thanks.

------
pfooti
My only wish for TS (which I use on the daily and love) is for some way to
export type annotations at runtime. Like I'd love to inspect a class property
and see if it is annotated as "this is a date" (in particular for
deserializing JSON, which is a constant bugaboo for me). Right now, I just
generate two parallel schema definitions, one that typescript uses to provide
compile-time type safety, and another that's just a pojo to access at runtime
to get more data.

~~~
styfle
Maybe something like this?

[https://github.com/YousefED/typescript-json-
schema](https://github.com/YousefED/typescript-json-schema)

------
moron4hire
With nodemon and live-reload, why is this an issue? I've been able to do
TypeScript apps in Electron for months. Both adding TypeScript and Electron to
my build process were afternoon projects. No, I'm not running TypeScript
natively. But where else do we ever run TypeScript natively? Retranspiling on
file changes works pretty well.

~~~
charrondev
Did you read the article? It’s running typescript without a transpiler in
electron (although I think there is a community project for that). It is about
electron shipping their own officially maintained type definitions in
the`electron` npm package for typescript users.

------
z3t4
does typescript know if a parameter is undefined (misspelled) or does it only
find errors like 1+'1' ?

~~~
0xcoffee
It is a full static checking system, so it will find obvious errors like
mistyping something, but it also infers alot of information from the context.

I made a small simple demo here:
[https://www.typescriptlang.org/play/index.html#src=const%20e...](https://www.typescriptlang.org/play/index.html#src=const%20example1%20%3D%20%22Hello%22%3B%0D%0Aexample1.length%3B%0D%0A%0D%0Aconst%20example2%20%3D%20Math.random\(\)%20%3E%200.5%20%3F%20null%20%3A%20%22Hello%22%3B%0D%0A%0D%0A%2F%2F%20Error%20-%3E%20Object%20is%20possibly%20'null'.%0D%0Aexample2.length%3B%0D%0A%0D%0Aif%20\(example2%20!%3D%3D%20null\)%20%7B%0D%0A%20%20%20%20example2.length%3B%0D%0A%7D%0D%0A%0D%0Aconst%20example3%20%3D%201%3B%0D%0A%0D%0A%2F%2F%20Have%20fun%0D%0Aconst%20example4%20%3D%20Math.random\(\)%20%3E%200.5%20%3F%20example2%20%3A%20example3%3B)

Note: Click Options and enable all the settings. Typescript works best in
strict mode, but it seems options arn't including in sharing via url.

~~~
z3t4
It seems it can only find properties if they are defined as foo = {bar: 1};
and not foo={};foo.bar=1;

------
donatj
From the video "Use --save-exact because […] we don't follow Semver"

------
vorpalhex
Why should I be cursed with the weight of your type system when I chose a
language without types?

If I wanted a typed language, _I would use a typed language_. JS has a lot of
benefits. Being able to use JS to make native-ish apps has it's place. Being
able to use typed JS to make native-ish apps probably means you should be
using a different language.

~~~
StevePerkins
> _If I wanted a typed language, I would use a typed language._

If you're doing server-side development, then you have a million languages to
choose from. If you're developing within the context of a browser engine, then
the choice was made for you over 20 years ago.

If you like that choice, then great. If you don't, then you transpile. Either
way, it's silly to act as if there's a contradiction here.

~~~
vorpalhex
But this isn't web development, this is a native-ish app. One certainly
doesn't need to us JS to make a native-ish app.

