
TypeScript at Slack - anaisbetts
https://slack.engineering/typescript-at-slack-a81307fa288d#1
======
boubiyeah
Typescript is a truly great project, I'm not sure many people understand the
amount of work that has gone into this compiler.

They have the crazy constraint of being 100% compatible with Javascript, which
is a bit broken by design and yet they managed to make it so much better to
work with TS than with JS.

After trying Flow numerous times, I came to the conclusion it simply can't
compete with the power of the team Microsoft put together. Even their alpha
versions are stable enough to be used in production.

Some advices:

\- Always enable --noImplicitAny and --strictNullChecks. Without these flags,
the type system is barely better than using JS.

\- Use a noAny tslint rule. disable it on a case by case basis, only in util
code. Most of the time, any is not necessary, often you can use {} or Object
instead.

\- You can get away with just using undefined everywhere, null adds no value.

\- Use union types. Make impossible data combinations impossible to write!
Example:

export type RemoteData<D, E> = NotAsked | Loading | Refreshing<D> | Success<D>
| Failure<E>

~~~
azylman
> \- Always enable --noImplicitAny and --strictNullChecks. Without these
> flags, the type system is barely better than using JS.

It may be a good idea to add those flags for new projects, but if you're
converting existing projects, that's just not feasible.

Further, you can actually see huge benefits just from switching to the
TypeScript compiler without any changes to your code.

At my last company, we started switching to TypeScript just by running our
large JavaScript codebases through the TypeScript compiler and installing type
definitions [1] for the popular libraries we were using. While we were doing
so, we started finding a lot of bugs in existing code that TypeScript was
detecting for us automatically by inferring types from how we interacted with
known libraries.

[1] [http://definitelytyped.org/](http://definitelytyped.org/)

~~~
jrhurst
What sort of bugs did you find? Were you able create replicate the regression
from a user endpoint?

------
vmasto
Although I don't use TypeScript (I'm looking at Flow more and more recently
instead) I have to acknowledge Microsoft's huge contribution to the JS scene
(and not only) with TS and VSCode, truly exceptional products.

What's more interesting to me is that everyone who converts their code into
Flow or TS immediately finds at least N bugs (albeit small).

It's also quite amusing that this article came out today where HN's top
article for a few hours was a bashing against Electron (and Slack
specifically).

~~~
djtriptych
And AJAX :)

I'm also really hoping that the current crop of JS programmers learn event-
driven / reactive style programming, and for that, RX is probably the best JS
library out.

~~~
nathan_f77
Man, there's so many tools and styles to learn and evaluate.

I'm still relatively new to React and React Native, and have enjoyed writing
some apps with Redux. It took me a while to understand the need for redux-
thunk, and now I'm about to get started with redux-saga [1].

I'm totally unfamiliar with RxJS, but some of the concepts sound familiar. Do
I need to learn and use RxJS if I'm already using redux and redux-saga?

I found this SO answer [2], and this post [3], which compares redux-observable
and redux-saga.

This guide [4] looks pretty good, too.

[1] [https://github.com/redux-saga/redux-saga](https://github.com/redux-
saga/redux-saga)

[2]
[http://stackoverflow.com/a/40027778/304706](http://stackoverflow.com/a/40027778/304706)

[3] [https://hackmd.io/s/H1xLHUQ8e](https://hackmd.io/s/H1xLHUQ8e)

[4]
[https://gist.github.com/staltz/868e7e9bc2a7b8c1f754](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754)

EDIT: OK wow, as soon as you get to the "double click" stream diagram (in link
[4]), it all starts to make sense. This is pretty amazing.

EDIT 2: The example on [http://reactivex.io/](http://reactivex.io/) is also
good. I didn't realize it was available for so many languages: Java, .Net, JS,
Swift. This sounds like something I need to learn.

EDIT 3: This is the best programming guide I have ever read ([4]). It starts
with a real problem, then goes on to show how you would solve it in RxJS in a
rudimentary and familiar way. Then it expands on and successively simplifies
that solution, to show how you would solve it in the idiomatic way. It's
really the perfect way to learn these concepts.

> A metastream for responses looks confusing, and doesn't seem to help us at
> all. We just want a simple stream of responses, where each emitted value is
> a JSON object, not a 'Promise' of a JSON object. Say hi to Mr. Flatmap: a
> version of map() that "flattens" a metastream, by emitting on the "trunk"
> stream everything that will be emitted on "branch" streams. Flatmap is not a
> "fix" and metastreams are not a bug, these are really the tools for dealing
> with asynchronous responses in Rx.

~~~
bpizzi
You might also like this: [https://github.com/Day8/re-
frame](https://github.com/Day8/re-frame)

It's not js/es6 (re-frame is a react-based redux-like framework for
clojurescript) but the author does a good job at explaining how reactive
programming go well with functionnal programming and immutability.

~~~
Stoids
That's one of my favorite repos to point colleagues to who feel overwhelmed by
modern front-end development. Doesn't get bogged down in tooling or
implementation details and explains at a high level the problems all these
libraries are trying to solve.

It's a good foundation to crudely explain the pieces. React-Redux connected
components are responsible for domino 1, Redux reducers domino 2, effects
libraries like sagas/thunks/observables domino 3, selectors/getters for domino
4, React and the VDOM abstracting most of the concerns domino 5 and 6 away
from you.

Obviously not perfect, but feels like it helps with choice angst a bit.

------
ng12
Typescript's single biggest win for me is the ability to provide type
definitions for my models. This is where the vast majority of my JS bugs come
from -- somebody trying to access a nonexistent property of some object (or,
if it does exist, incorrectly assuming the type) which was serialized from
JSON. Better yet, if you write your back-end in Node you can use the same
models in your rest endpoint. It's a huge boost to both maintainability and
developer productivity.

However, my biggest frustration with Typescript is the general unreliability
of @types. The odds that a given set of typings are complete, correct, and up-
to-date are basically nil -- even for some relatively popular projects. Sad to
say I've become an expert in Typescript's crazy module augmentation nonsense.
Hopefully more big players like Slack contributing to DT will help.

~~~
sadlion
How does one validate typescript models at runtime? I have seen combinations
of JSON schema and validator libraries but I'd love to do it using
typescript's type system. From my understanding, it doesn't work because of
type erasure.

~~~
ng12
AFAIK there's no good solution. That's why it works best when your back end is
using Typescript as well -- your route returns the same interface the client
is expecting.

~~~
jononor
This goes out the window when you have multiple deployed/running versions of
your client or server.

~~~
mercer
Would one solve this by versioning the types somehow? Honest question; I'm
pretty new to TS.

------
nathan_f77
Where can I find a good list of pros and cons for Flow and TypeScript?

I've been really enjoying Flow, and I have experienced all of the benefits
mentioned in this article. I'm using VSCode, and the Flow integration is
really good. Feels like a full IDE for Javascript, without being bloated and
slow. (Startup is a little slower than Sublime, but it's very fast once
everything has loaded.)

I'm wondering if I'm missing out on anything by choosing Flow instead of
Typescript.

I've been developing React and React Native apps, and it seems like Flow is
the default choice for that ecosystem. Has anyone switched from Flow to
Typescript, and how did it go?

~~~
yjgyhj
I've used TypeScript, Flow and Elm for making front-end apps. My favourite of
the three is by far Elm, even if that was a bit harder to get into (as it's a
new language and I didn't know before how to do side-effect free programming).

Flow is definitely a better type system than TS. TS types are "strong" in the
same way as Java types. Flow is basically OCaml types, so a similar type
system to OCaml, Haskell or Elm (except that you can give things `any` type).
I am sure I will chose Flow over TS for that reason.

A ML-type type system (Flow, OCaml, Haskell, Elm, etc) is very powerful in
that you can have abstract types, which means you can do basic composition of
them. Things like the Maybe or Result monad for instance, which is very useful
(and simple).

Typescript on the other hand let's you use the basic JS types, but it's not as
extensible.

~~~
paavohtl
Do you have any examples to back up your claims? I don't think Flow's type
system is more advanced than TypeScript's (which is not Java-like in any way).

What do you mean by "abstract types"? TS's type system is based around
structural interfaces, so you're almost always working with non-concrete
types.

It also supports discriminated unions, and you can emulate nominal typing with
abstract tag properties.

[https://www.typescriptlang.org/docs/handbook/advanced-
types....](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
[https://basarat.gitbooks.io/typescript/docs/tips/nominalTypi...](https://basarat.gitbooks.io/typescript/docs/tips/nominalTyping.html)

------
Androider
Question for TypeScript users from someone who's still on the fence: Are you
at all worried that TS will end up like CoffeeScript?

That is, it starts out with some great ideas that are quite easy to get
behind, but JavaScript keeps on advancing year after year and soon you have
the same features available but with an annoyingly different syntax, or you
actually end up falling behind the curve. You're also not able to simply use
the latest JS features, my last attempt at adopting TS died when I found it
didn't at the time support object rest and spread properties, which I had been
liberally using via Babel for quite some time.

It seems like Flow is a "safer" choice to me, but I'd love to hear if you
disagree.

~~~
evmar
The delta between TypeScript and the JS standard is very small (for many TS
users I expect it's a trivia challenge that they won't be able to answer:
"write a TS program that isn't valid JS once you erase the types").

As you yourself point out, you were using features that weren't in a browser
and needed a different transpiler to implement them. I think object spread
still isn't even part of the standard(?) and you could imagine the standard
diverging from the babel implementation of it, so the risk is mostly the same
there.

The TypeScript team is pretty committed to tracking the standard, and e.g.
turn down feature proposals that aren't far enough along in the standards
process. See
[https://github.com/Microsoft/TypeScript/issues/16](https://github.com/Microsoft/TypeScript/issues/16)
for a feature users are begging for that they aren't implementing. Another
good example is that they had their own module system which they deprecated in
favor of the ES6 module system.

[disclaimer: big TS fan; I think Flow is fine too but I don't think it offers
any advantage with respect to the issues you're concerned about here]

~~~
riquito
> As you yourself point out, you were using features that weren't in a browser
> and needed a different transpiler to implement them. I think object spread
> still isn't even part of the standard(?) and you could imagine the standard
> diverging from the babel implementation of it, so the risk is mostly the
> same there.

That's why there are stages and you should use at least stage 2 (draft)
[https://babeljs.io/docs/plugins/preset-
stage-2/](https://babeljs.io/docs/plugins/preset-stage-2/)

------
ken47
Typescript is GREAT. Strict null-checking eliminates the dreaded null-pointer
exception. It enables type-safe mixins. It allows for mapped types. Literal
types, especially string literal types, makes it so easy to work with pre-
existing JS libraries.

The way I look at Typescript vs. Javascript is that with Typescript, it's like
having always having a pair programming buddy (the compiler) who never makes
mistakes.

~~~
technion
null checking can have some surprising results. The standard React pattern:

    
    
            ReactDOM.render(
            <Start />,
            document.getElementById("content")
            );
    

Will error because getElementById can return null. And it's 100% valid and imo
100% worth checking for - but I can't say I've ever heard of anyone doing it
before Typescript suggested it.

~~~
Ycros
2.0 added an exclamation mark (!) postfix operator that asserts a type as
being non-null/non-undefined. So these checks are easy to explicitly ignore.

~~~
technion
Thanks! I wasn't aware of that. That said, I don't actually want to ignore it
- I think it's good that Typescript is showing people some potentially errors
they never thought to look for.

This pattern really isn't hard and if it saves you from one "undefined is
undefined" then it was worth it.

    
    
        const item = document.getElementById("content");
        if (item == null) {
            console.log("Render container missing");

------
felixrieseberg
Hey! Author here - let me know if you have any questions about anything in
that post (or, you know, anything else... like, erm, Electron).

~~~
sydd
> To improve our situation, we decided to give static type checking a shot.

I wonder why it took you years to realize this. I'd never use a dynamically
typed language for more than a few hundred lines of code, it becomes an
unmaintainable mess afterwards. So serious question: Why?

~~~
azrazalea
In case you are wondering about the downvotes:

There are millions(trillions?) of lines of code out there that is maintainable
and dynamically typed.

~~~
jiaweihli
Maintainable, but at what cost? A large chunk of unit tests for dynamically
typed code is dedicated to checking types.

------
LeoNatan25
> TypeScript at Slack

> Or, How I Learned to Stop Worrying & Trust the Compiler

So revolutionary. Who knew that compiling code has advantages over interpreted
scripts.

~~~
iends
I'm not sure what you're trying to convey. Most/All? modern JavaScript engines
compile JavaScript (including v8).

~~~
dimgl
lolwat?

~~~
chillacy
I think the parent is referring to JIT Compilation as a type of "compilation"
as opposed to being interpreted. Of course the original post is tackling the
type-safe aspect of compiling vs performance.

------
ChicagoDave
A slightly forked discussion, but having been in IT for over 30 years, I sense
a theme...

A long time ago, people argued over the merits of assembly versus C.

After that, people argued over Pascal over C.

Then BASIC caused all kinds of consternation. BASIC versus "structured
programming" was a common argument. With BASIC, there was this sort of
wildness to it that drove people crazy. (this should be sounding familiar)

Then Visual Basic added structure (procedural at first, OO in .NET).

Then JavaScript was added to browsers and everyone cried that it was too
unstructured and "wild".

Then Google Maps was released and JavaScript suddenly became popular.

Then NodeJS solidified JS as a real solution.

Now TypeScript comes along to make JS more "structured" and we have the same
old arguments. Structure over low level unconstrained programming.

The weird part (to me) is that each side garners the louder voice about every
ten years.

I'm pretty sure some new-fangled unstructured platform will arrive in 2020
that everyone will jump on and say is better. It offers freedom and the
ability to sculpt a vision that the structured platforms don't.

Am I right or am I right?

~~~
krona
One significant difference with the past examples you cite is that Typescript
is _gradually typed_ , so it's a false dichotomy you're presenting. Personally
I think this is one of Typescript's biggest achievements, since the Typescript
programmer gets to decide how _structured_ their system should be.

~~~
ChicagoDave
Maybe. But anecdotally I've heard from more than a few JS devs that they'd
_never_ learn TypeScript because it adds structure they don't feel is
necessary and that just following ES6 is good enough.

~~~
vladimir-y
> Maybe. But anecdotally I've heard from more than a few JS devs that they'd
> _never_ learn TypeScript because it adds structure they don't feel is
> necessary and that just following ES6 is good enough.

My guess is those were not an engineers, but script kiddies / code monkeys.

~~~
ChicagoDave
There are a _lot_ of those these days.

------
jondubois
I do not particularly like TypeScript because:

\- It adds complexity and unnecessary dependencies to the project and this
makes it more brittle and more difficult to set up and get running (I often
run into issues with it). \- Slows down your debug cycle (it typically takes
at least 15 seconds to compile for a small project) so you can't test your
assumptions quickly as you would with plain JS - You have to wait all the time
and try not to get distracted. \- For an experienced JS developer like me, the
vast majority of errors raised by the compiler are pedantic and not related to
any real logical flaws - I spend a lot of time catering to the fussiness of
the compiler instead of thinking purely about logic. \- Working with legacy JS
libraries is a pain.

I will admit though that being able to look up references and usages of
various classes and functions without having to leave the IDE is a nice
feature - I don't really need it though because I got used to searching
through my code with text-matching (sift) and by adhering to a proper source
directory structure.

~~~
parent5446
Surprisingly I have not run into those compile time issues. Maybe it's just my
company's own infrastructure, but our TS projects, which can get rather large,
all recompile in less than five seconds.

~~~
jondubois
Yeah I'm not sure why it takes so long for me. We're using Angular 2.

------
tabeth
I haven't used TypeScript yet, but it seems like it's similar to a pattern I
sometimes use, like the following:

    
    
      function foo(a, b, c) {
       g.param(String, a); 
       g.param(Object, b);
       g.param(XMLHttpRequest, c);
    
      /* stuff */
    
       g.return(String, bar);
      }
    

Seems like the main benefit to using TypeScript is that it can tell you if you
have poor types during "compile" time, right?

I guess the question for me is, is TypeScript superior than the above pattern?

~~~
chillacy
Autocomplete is a big productivity boost too: VS Code will suggest methods on
the object, then tell you exactly what arguments it takes and what types they
all are.

Of course maybe you can have another system which reads in the code you have
and autocompletes for you too.. after all, the type info is all there, it's
just in a different place. Compared to everything in the function definition:

    
    
        function foo(a: string, b: object, c: XMLHttpRequest): string

------
iamwil
After using types in Elm, types in Typescript have felt like a step backwards.

~~~
bbcbasic
After using types in Haskell, types in Elm also feel like a step backwards.

~~~
weavie
After using types in Idris, types in Haskell feel like a step backwards...

~~~
bbcbasic
A nice poset developing here.

------
anko
one thing I wish typescript had was an ability mark typechecks as runtime.

Commonly I'll have a nodejs express app which serves an api and i've love a
easy way to validate an interface against the payload passed in. Maybe it
would be as simple as a function JSON.parseWithChecking<User>(payload) or some
annotation to get the interface reflected and passed into this function at
runtime. It's normally always at deserialisation that this problem occurs.

~~~
whatever_dude
Wouldn't it be better to use a JSON Schema validator in this case?

~~~
anko
Then you're maintaining two definitions - typescript ones and json schema
ones. But thanks for the idea :)

~~~
gcanti
You could write the runtime definition and extract the static types from that
[https://github.com/gcanti/io-ts](https://github.com/gcanti/io-ts)

~~~
anko
thanks for the link - i've never seen that before :)

------
misotaur
Is Typescript already supported on most browsers or do I need to install a
library?

~~~
whatever_dude
Typescript doesn't need browser support, it's transpiled as JavaScript.

------
msie
The more code is in TS, the easier it is to write tools to manage that code.

------
blauditore
The article mentions multi-threaded desktop applications along with JS. Since
JS is inherently single-threaded, what does that mean? Do they actually refer
to multiple processes or some other magic?

~~~
chickenfries
JavaScript doesn't really have "threads" but node JS has it's `child_process`
module and the browser has web workers.

~~~
blauditore
Yeah, but Node child processes are actually separate OS processes, which
behave quite differently from threads (higher overhead to spawn, separate
memory). The same goes for web workers; they're more like daemon processes
than different threads. So I guess this was just poor terminology in the
article, not any new magic... :)

------
jacobr
Last time I tried TypeScript we ended up abandoning it after having mismatches
between dependencies and TS definitions.

We had to postpone upgrading libraries to wait for definition updates or write
and maintain them ourselves. This was in the early stage of a project though,
we needed to get a quick first version out in 2 weeks and it just wasn't worth
the hassle.

Has this situation improved - I understand typings are no longer installed
with a 3rd party tool/registry?

~~~
Ciantic
There is one significant change with TS 2.2, you don't have to use type
definitions for libraries anymore. Since all JavaScript is valid TypeScript.

With out of the box setup the import from library that has no type
definitions, works just fine. It returns `any` type, so you can use all
libraries just like you would in JavaScript. So if you ram your head against
bad type definition of a module, just delete it and continue using it like you
would in normal JS.

------
vinhboy
> he did not expect how far the Slack Desktop App would take his invention

Kind of funny to read this article, after just reading that Electron article.

------
pacoverdi
I have become a create-react-app junkie but unfortunately TS is still not
(officially) supported in it [1] so for the moment I stick to using flowtype.

[1] [https://github.com/facebookincubator/create-react-
app/issues...](https://github.com/facebookincubator/create-react-
app/issues/142)

------
rdiddly
I've been working in this kind of environment with strongly typed languages
for a long time, but TypeScript might be the thing that gets me to go back &
give JS another chance. Funny to be coming at it the other way!

------
uranian
I really don't understand why some developers are so happy with Typescript.
Javascript was already years ago highly improved with transpilers like
Coffeescript, Livescript etc..

IMHO this whole Babel, ES5, ES6, ES7, ES???, Typescript thing with it's
countless options is much worse than simply Coffeescript with a dynamic type
checker. I use the latter in quite some production environments currently. No
need for Babel, Typescript, linters etc.. It really makes my life way, way
easier, less npm modules, less bugs, less lines of code, much more readable,
etc, etc..

And please, before you start preaching all those 'amazing' benefits of Babel,
Typescript, linters, ES5, ES6, ESx, I come from that misery and it sucks!

~~~
kgabis
Would you rather have your program fail at runtime instead of using a
statically typed language? It really baffles me why so many people prefer
dynamically typed languages and write large projects in them.

~~~
uranian
My apps don't fail at runtime because of type errors, at least, not that I
remember. It really baffles me how many people need Typescript to avoid having
type errors at runtime, what the hack are they doing wrong then? This is not
C++, we only have a few types in JS, really hard to mess up for me.

~~~
kgabis
Are you serious? You can define custom types in javascript, nobody programs
using only primitives like strings, numbers and booleans.

------
renlinx
Instead of wasting time on this, try to understand javascript, Why slack web
app & desktop app(electron) is taking too much cpu & memory, it will help
you...

------
mi100hael
Slack & its use of JS are sure getting a lot of attention on the front page of
HN today...

------
z3t4
I'm a strong opponent against type annotations in JavaScript. JavaScript only
have a few types: strings, numbers, boolean, null, undefined, and Symbol
(ES6). And annotating them feels stupid. Feel free to use Flow, Typescript
et.al. but let the type inferencer do the work, not you. You should only have
to think about the abstract meaning of the code. And pick good names for
variables and functions. In order to catch more parameter errors, your
functions should throw errors if the parameters are incorrect!

------
throw5938
Seems like Apple needs to disincentivize the use of Electron and other user
hostile technologies somehow before anything will change.

They also need to crackdown on the Facebook app.

[http://blog.timac.org/?p=1707](http://blog.timac.org/?p=1707)

