
Convert React JavaScript Code to TypeScript with Proper Typing - styfle
https://github.com/lyft/react-javascript-to-typescript-transform
======
soulnothing
I recently started a new project. I started with kotlin and react. I was
working on creating typings for redux, router, etc. Encountered a lot of
issues.

Moved to typescript, things were great till I went to add redux and router.
There were typing issues being worked out in the recent development branch. A
few weeks back.

I love typescript. The IDE experience via visual studio is great. But I was
burning a lot of time working on type libraries/definitions.

I switched to flow. I miss visual studio code and some of the typescript
features. But adding typing to a react project, especially with redux and
immutable is great. The typing ecosystem of flow and typescript is truly
impressive. With support for union types, strong structures. Really good
inference. I'm just waiting for better pattern matching with active
expressions. Please steal that from F#.

This is also interesting for kotlin.
[https://github.com/Kotlin/ts2kt](https://github.com/Kotlin/ts2kt)

~~~
Karnickel
I've been a heavy user of Flow for - two years now? I also occasionally use
TypeScript. I don't contribute to the code _(in the Flow case, I don 't speak
OCaml, I contributed a bit to the type library and the online docs; in the
case of TS, I don't use it enough)_, but I write a bug report each time I find
an issue.

I've been looking at the issues list very often, mostly out of curiosity to
see what the problems are that people have (both Flow and TS) and to see which
project is better at solving problems.

TypeScript seems to win hands down. Their ratio of closed tickets to open
tickets is far better than that of Flow:

\- TypeScript: 2,515 open, 12,716 closed --
[https://github.com/Microsoft/TypeScript/issues](https://github.com/Microsoft/TypeScript/issues)

\- Flow: 1,830 open, 2,467 closed --
[https://github.com/facebook/flow/issues](https://github.com/facebook/flow/issues)

I have to assume they mostly close issues after solving them - it is not
unheard of that issues are closed merely because they've been lying around for
a few months without any updates (definitely happens for Flow).

I prefer the approach of Flow, but I think the actual developers are not
present at all on Github, most answers come from other users. There are very
few actual solutions to issues that are raised. The list of issues grows ever
larger. Flow _does_ make progress, and it's not even bad. Every 10-15 days we
get a new release and I'd say the progress is quite okay. What went really
well the last 12 months was IDE integration for Flow in the case of Jetbrains
Webstorm (for TS the situation always looked good), as of now, latest Webstorm
version, it's actually usable. I still get too many Flow server crashes
though, which may be due to my platform (Windows 10), not sure. However, it's
now automatically restarted most of the time.

A TypeScript anecdote: I filed an issue that a "Member" closed as "works as
intended" after a few comments back and forth (but it was clear right away
that this would be the end). I filed it again - this time Anders Hejlsberg
himself responded and acknowledged the issue (it _was_ kind of fundamental and
not just something unimportant), and it got fixed. So here too you need a bit
of luck to get through to someone who actually understands the subject well
enough (including knowing when they don't understand it, if that first guy had
just stopped handling my issue it would have been fine). But that's the price
of using a popular large project, so this is not a complaint - just an
anecdote, okay?

What I do get for myself after following the two type systems for well over
two years is that there are LOTS of restrictions. Just read some of the issues
in both Github repos, it's really interesting.

I find the whole situation very unsatisfying. It is clear - when you actually
use it heavily for a big project for a longer period - that a type system on
top of Javascript is very difficult to maintain. LOTS of unsolved cases and
issues. You definitely have to adapt and use only the subset of Javascript and
the type system that works. I validate an object manually and I still have to
do an "any" cast in Flow because Flow does not recognize that my `if`
statement secures the type. Or I have to insert such `if` statements even
though from the context it is perfectly clear what I get there. For example,
any inner functions, e.g. when using map, filter, reduce, loses the type if
you use a variable from the outer scope. Or you have to use a lot of
additional `const` for object properties even though you don't change the
object - but the type checker is not intelligent enough to recognize that. You
definitely write different code - and while that may seem okay there are
plenty of cases where it really is objectively unnecessary, but you have to do
it to satisfy the type system.

On the bright side, once you get your code all "type system ready" you really
_do_ find bugs - even if it's just a few. Also good is that I now get much
better autocompletion suggestions in the IDE. There's a reason why I (as
project head) still insist on us using Flow even though I say "WTF?" often
enough. It _does_ cost a significant amount of time though - a _very_
significant amount. I've been willing to do it because of the kind of project,
which is going to be a very low-level building block for later larger
projects, so it is worth spending a lot more resources on getting it right
compared to a project that's on a top layer, on which nothing else depends.

Still, overall I have very mixed feelings and I see the type checkers (both TS
or Flow, or any other that could be written) on top of a language that doesn't
have types as a kludge that does not look like a long-term solution. There is
too much friction between the language and the type system.

~~~
WhitneyLand
The question is why don’t they collaborate and unify the efforts?

It seems it should only not happen for a handful of reasons.

For example, if there were real intractable philosophical differences, if
someone risks losing strategic advantage, or if competing is driving better
results than collaboration could.

Yet it’s not obvious to me how any of these are true.

For many projects unification wouldn’t make sense by a mile even for reasons
not listed here.

I don’t even see how the existing skill sets are tragically different, say
like the the skill sets are so different for Linux/Windows admins who could
never master the other’s job in a week.

In this case maybe there are reasons for separate projects but are they really
super compelling?

Imagine the (potential) upsides of having more resources, less confusion, and
more comprehensive tooling support.

To me they are both useful projects but I don’t see any fundamental advantage
of one over the other that would make me lose sleep if everyone rallied behind
a single effort.

~~~
shados
The JS type system world has benefited a lot from NOT having a monopoly. When
Flow started gaining some traction, the whole "handle nulls properly" thing
was a huge. During that time, the TS issue tracker was filled with comments on
how it didn't really make sense. I don't think TS would have ever gotten
strict null if Flow didn't "compete" with it.

Them being separate allows the projects to try stuff the other group disagrees
with and prove they are right. I very much like that.

Beyond that, the 2 projects really are VERY different. Again, with strict null
and all the pain, it's causing on the TS side. It's not easy to just bring in
features of one and merge them to the other. The entire architecture is
different (eg: the flow inference). Then there's the pitty shit: I don't know
if they're involved with TS, but some very visible Facebook people just can't
handle the fact that the entire world doesn't revolve around Unix, as nice as
it would be if it did.

Some stuff is sparking some collaboration. Babel getting support for
TypeScript syntax for example.

~~~
O4epegb
Strict null in TS was before flow public release.

~~~
gr__or
That is not true at all!

Flow was announced November 18, 2014:
[https://code.facebook.com/posts/1505962329687926/flow-a-
new-...](https://code.facebook.com/posts/1505962329687926/flow-a-new-static-
type-checker-for-javascript/)

Typescript got --strictNullChecks with Version 2 which was announced July 11,
2016:
[https://blogs.msdn.microsoft.com/typescript/2016/07/11/annou...](https://blogs.msdn.microsoft.com/typescript/2016/07/11/announcing-
typescript-2-0-beta/)

Even if I'm being charitable and look for the date when the PR
([https://github.com/Microsoft/TypeScript/pull/7140](https://github.com/Microsoft/TypeScript/pull/7140))
was merged, we'd only get April 2016.

------
mohsen1
Author here, ask me any questions you might have. We used this internally to
convert a few repos. It's not perfect but gives you a head start for
converting to TS.

I also wrote about our experience with TypeScript at Lyft if you're
interested:

[https://eng.lyft.com/typescript-at-
lyft-64f0702346ea](https://eng.lyft.com/typescript-at-lyft-64f0702346ea)

~~~
scoot
Not specific to your project, but I suspect you’ll know the answer: If React
code contains sufficient information to infer type, why is a separate type
system needed? (Or why can’t the same inference by made at compile time,
rather than scattering the code with type definitions and external type
files?)

~~~
msoad
Because propTypes are leaking into runtime. ASFAIK Flow originally wanted to
use propTypes but decided to use compile time only type annotations

------
ggregoire
Same for Flow: [https://github.com/billyvg/codemod-proptypes-to-
flow](https://github.com/billyvg/codemod-proptypes-to-flow)

------
seekbeak
Please work. Please work. Please work. This couldn't come at a better time.
I've got "convert site to TS" looming on my to-do list for a large web app.
Anything that saves me some interface props/state typing tedium would be
great.

~~~
agopaul
I plan to move a small react project to TS so it will be easier to work with
complex objects coming from API endpoints. Having used TS quite a bit with
"vanilla" JS and seen the advantages of using strong typing (eg. easier
refactoring), it's strange for me to see that the majority of React developers
prefer to stick with ES6 instead of TS

~~~
ggregoire
Most JS developers have no or few experience with strongly typed languages. I
think it's a thing you need to try by yourself to see the benefits. I was kind
of an anti-TS some years ago ("it's too verbose, it's not JavaScript"), but
since I used Flow for 1 year I now see the obvious benefits (my favorite being
to have autocompletion for almost anything, and not having to wait the runtime
to see that `user.fisrtname` is undefined).

Also, probably some React developers would like to use TS/Flow and their
manager says 'nope'.

~~~
seanmcdirmid
I’m a heavy TS user, but the compilation step is a PITA compared to working
with bare JavaScript. Sometimes I forget to build and I wonder why my program
hasn’t changed.

I wish browsers would suck in TS directly. It doesn’t require much translation
to get the corresponding JS files, just ignoring some types and that’s it.

~~~
52-6F-62
Against watch scripts for any reason?

It's pretty simple to get TS building via webpack for react, and tsc itself
has a watch mode. The only PITA there is if you save any breaking changes, the
build will obviously fail until you've completed and saved any the working
changes, but at least you can't forget.

~~~
seanmcdirmid
I seem to forget to save sometimes also (granted, that would mess me up with
javascript also), I'm just so used to straight C# in Visual studio!

Typescript also isn't a very fast compiler, it doesn't seem to be incremental
or retained at all, so when you build your project, it take a few seconds when
your project has grown beyond a certain size. Sometimes I build and then hit
run too early (before the build is actually finished).

~~~
52-6F-62
Ah yeah. I guess Webpack's boost would be lost if your project ends up at all
complex as well.

Are you doing all of your TS dev in Visual Studio as well?

~~~
agopaul
I'm using webpack on a ~60 TS files project now. It takes a few seconds to
bootstrap, but then, in watch mode, it only compiles the files that are
changed and it's really fast.

------
Waterluvian
I really want to commit to TypeScript for React/Redux apps but I'm gun shy. I
don't want to commit to all the added effort TypeScript brings because I'm not
sure if apps of my size warrant it. I'm afraid that I will end up with an
over-engineered solution for my various apps of 10-100 components.

~~~
seekbeak
It's such a no brainer after you use it for a while, and the time savings
after the fact far make up for the initial learning curve.

Just do a small project to muck around with first. Maybe something small that
nobody has thought of, like a to-do list?

~~~
gedy
> and the time savings after the fact

Could you elaborate how? I used to heavily use typed languages, but after
moving to JS 5 years ago, I don't miss types.

~~~
ggregoire
\- Get autocompletion for everything: object properties (eg. user.[firstname,
lastname, etc]), type-specific methods (eg.
thisIsAStringButYourEditorCantKnow.[list of string methods provided by your
editor since you told him it's a string]), etc

\- Detect bugs and errors early, removes some kind of bugs (eg. typo errors:
user.fisrtname, your editor will tell you fisrtname is not a property of user)

\- Help to refactor (eg. 'Rename Symbol' in VSC can't work on everything if
your code isn't typed, eg. (X => X.someProperty), someProperty isn't renamable
automatically since your editor doesn't know what's X)

\- Reduce extra error handling (eg. if (a === undefined || b === undefined ||
a is not a number || b is not a number) throw new Error(...))

\- Reduce extra unit tests (eg. expect(add(5, undefined)).toThrowAnError();
expect(add(5, 'foo')).toThrowAnError();)

\- etc...

------
towndrunk
Take a look at some of the code samples in this post where the author is
trying to make Redux work better with types in TypeScript. In my opinion, you
get to the point where the code looks a mess and looks difficult to maintain.
There is no way a beginner is going to figure this all out.

[https://medium.com/@danschuman/redux-guards-for-
typescript-1...](https://medium.com/@danschuman/redux-guards-for-
typescript-1b2dc2ed4790)

~~~
spion
That article describes all the steps he took to get there, and he simply
didin't make it clear what of that was included in the end result (its just a
generic action creator and type guard)

------
ralmidani
Has anyone considered building with TS--from the ground up--a React-like
library? It seems like TS could help deal with lots of data and validation
errors in a more concise and predictable way.

~~~
bcherny
React is already typesafe.

For Redux I wrote Babydux [0], which is a simplified Redux with the goal of
being 100% typesafe. It's the only Redux I've seen with that level of safety.

[0] [https://github.com/bcherny/babydux](https://github.com/bcherny/babydux)

~~~
styfle
"Redux for babies" sounds like an insult.

It reminds me of this Nathan For You episode:

[https://www.youtube.com/watch?v=BNuuiydKlI0](https://www.youtube.com/watch?v=BNuuiydKlI0)

------
benjaminjackman
So proptypes can be inspected at runtime. Does anyone have any success with
tools that can turn Typescript types into runtime walkable datastructures or
do code- generation / execute macros based on them as part of the build
process?

I use typescript quite a bit and am starting to hit some patterns that could
be abstracted nicely if metaprogramming tools were in the shed.

~~~
joe-stanton
You might be interested in this: [https://github.com/gcanti/io-
ts](https://github.com/gcanti/io-ts) and many related projects by Giulio.

~~~
joe-stanton
Beforehand I built something very similar to what you described for Flow
([https://hackernoon.com/runtime-introspection-of-flow-
types-d...](https://hackernoon.com/runtime-introspection-of-flow-types-
ddb7e5b042a5)).

Many others superseded this implementation, the above being one example.

------
jorblumesea
I just flipped over my React app to typescript + react, and as a word of
warning, support for some React libs is sketchy. For example, typings for
redux Thunks are wonky/problematic and required a few hacks to fix. Very cool
stuff just buyer beware :) You will probably have to work around more than a
few issues if you use anything more than vanilla React.

~~~
styfle
Nothing that a little `var unsafe = original as any;` couldn't solve!

~~~
cloverich
To be a bit more explanatory: You can cast to the "any" type by adding `as
any` to any variable, and it will then work just like Javascript. Typescript
will know not to infer types from it or complain about it, and for that
variable (which could be a simple variable or an entire library) will work
just as it would in regular javascript. I typically use this when testing out
a new library that doesn't have Typescript types so I can get a feel for it
(and if I like it, I"ll progressively add types to it; its a very nice process
imo).

------
TheCoreh
Looks really nice! I have an existing codebase that I might try this on.

One feedback: Wouldn't

    
    
        interface MyComponentState {
          foo: number;
          bar: string;
          baz: number;
        }
    

Be a little more idiomatic than

    
    
        type MyComponentState = {
          foo: number;
          bar: string;
          baz: number;
        }
    
    ?

------
ComputerGuru
Why is lyft in the title?

~~~
forgot-my-pw
It's their repo.

