Hacker News new | past | comments | ask | show | jobs | submit login
Convert React JavaScript Code to TypeScript with Proper Typing (github.com/lyft)
216 points by styfle on Jan 16, 2018 | hide | past | favorite | 119 comments



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


with either TypeScript or Flow, you can't go very far before hitting type definition hell. It just shifts where the hell is. Flow has better types out of the box for the Facebook ecosystem, and the flow-typed types, if they're available, are generally higher quality (unless it's for a lib that was made with TS in mind, like RxJS). TypeScript has massively more typedefs of highly varying quality, and there's more stuff written in TypeScript itself. However, so many of them are broken or are incompatible with strict mode (next person who says TS matches Flow because it has strict null can take the door, thx). Fortunately, TS makes it much easier to override broken type definitions.

It's a real toss-up which one is better, but both are filled with tears and pain. That pain can (and is often) worth it, but it's absolutely not the slamdunk people around here make it out to be.

Unless you REALLY like abusing the any type, in which case what was the point again?


I don't mean this dismissively but Typescript's type system is insanely flexible, and _should_ let you do basically anything you want. Especially when you look at union types, sum types, type guards, the `never` type....

As a bonus, if you are willing to generate type definitions from other sources (like your backend code) you can go super far.

I do agree that the current `@types` solution without versioning isn't very great. Though I've found that for libraries without good definitions, hacking out a simple interface for the layer you use is good.

Just doing interface SomeLib {}; declare var lib:SomeLib; and then filling in the errors can be pretty quick in most projects.

It makes sense to use libraries, but writing up an interface definition for a library you use is usually quick enough.

I'd love to hear about cases where type definitions really messed you up.


Properly type lodash or ramda's curry in TS. All the versions I find basically make 5+ overload and a sloppy fallback. Flow can actually type it correctly but so few people know, even the flow typed version doesn't do it (last I checked).

There is also plenty of awkward places. Take the Apollo React HOC which can be used for query or mutations. It only achieve this by giving you an object that can be one or the other but you have to know which one you're getting.

Another common example is the redux case. You have the store which is of a type. The HoC gives you a function that takes an argument of that type. Nothing links the two though because it wasn't designed with types in mind, so you have to specify the type yourself (essentially a pinky swear). If it was designed with types in mind, the HOC/connect function would be created from the store, thus providing proper type safety.

Examples like this are pervasive. You can "type" most things, but in many cases you have to rely on sloppy methods that look type safe but really aren't.

If you write stuff with TS in mind from scratch, and use strict mode, it's another story. The type system is quite good.


I've had the same experience as you did. When there's no type definition available, starting from an empty object quickly resolves a lot of the issues. But that really depends on the complexity of library you're trying to declare.

On the other side, I've also had cases when the type definitions were a pain. We have a web app and use .Net/TypeScript/React. We also use the commercial Kendo UI version. Since there's no versioning available (and the Kendo UI team doesn't seam keen on "type correctness"), we are (almost) always using a type definition file for another (newer) version of Kendo UI. We've had to "patch" the definitions on several occasions.


I really like Typescript. It's really well designed and gets typing right IMHO: Strong enough to help you where it matters, flexible enough to get out of the way where it doesn't.

Also, type definition hell is definitely a thing. Trying to match types to code often makes me feel like trying to match subtitles to a movie. Off to podnapisi, pick what looks like the best subtitles, fire up VLC, oh shoot, subtitles are ten seconds off, timeshift subtitles to match, watch movie until we reach the first director's cut scene, now subtitles are off again and wife in open rebellion. Which is probably the main reason that we subscribe to Netflix these days instead of trying to bootleg our way through. I'm digressing.

Anyway, it seems to me that after they started adding typescript typings to npm, everything has become more sane. At least for the more popular libraries, I rarely run into typing hell anymore. Less popular libraries, yeah, sometimes there is no typing, or sometimes the typing may still be off, but then I just give up and use "any". And these cases seem increasingly rare.


Have you seen Reason yet? It has pattern matching.

https://reasonml.github.io/docs/en/pattern-matching.html


That's pretty much the only thing I like from reason.

it's still very goofy.

<strong> (ReasonReact.stringToElement(string_of_int(count))) </strong>

Compared to

<strong>{ count }</strong> in ReactTS...

The interop with JS is pretty verbose too. The tooling... Doesn't work at all? :p It might get there eventually but it doesn't seem like facebook has more than 1 or 2 engineers working on it.


  <strong> (se(count)) </strong>
I’ve just built a tiny utils.re file that holds a couple of small modules, like the se function above. The built in reducerComponent with a completely flat pattern matching on the action types, values, arity and more is so lovely that I hate going back to regular React + Redux


Can you post that util file as a gist?



(ReasonReact.stringToElement(string_of_int(count)))

MV. Bold choice.


I haven't yet thank you. I like the ocaml influence.


Since you mentioned F# above, have you seen Fable?

http://fable.io/


ReasonML is OCaml. The syntax is different but the semantic is the same, it uses the same OCaml compiler


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

- Flow: 1,830 open, 2,467 closed -- 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.


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.


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.


Strict null in TS was before flow public release.


That is not true at all!

Flow was announced November 18, 2014: https://code.facebook.com/posts/1505962329687926/flow-a-new-...

Typescript got --strictNullChecks with Version 2 which was announced July 11, 2016: https://blogs.msdn.microsoft.com/typescript/2016/07/11/annou...

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


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

I have really wondered this. I suspect that the two projects had slightly different goals in the beginning, and are now slowly borrowing ideas from each other.

I think the only way they could truly merge is if ECMAScript standardized the subset which they both use and then TS and Flow could be used to introduce experimental proposals kind of like Babel does now.


I completely agree except for the part where it's useful.

In my mind, Flow is dead. The issues are mostly ignored, third-party type definitions are sparse and of varying degrees of bad to completely wrong.

> 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.

Agreed. This is a tough problem and it's a never-ending maintenance battle. This is especially true for an ecosystem that prides itself on making npm packages as small as possible ... they all need typings!

> 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.

> ... even if it's just a few.

This is exactly the conclusion we came to in our large codebase and we decided to rip it all out. We didn't see the win at all. We ripped it out and didn't notice a single difference in our dev workflow. We also got the benefit of reducing our syntax cognitive load.

> There is too much friction between the language and the type system.

Agreed. An optional type system is a maintenance nightmare. The amount of time it takes to get it right cannot be understated. It wasn't worth it for our large web application and the benefits are so minimal imo.


> 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.

Try this instead:

    import { reify } from 'flow-runtime'
    import type { Type } from 'flow-runtime'
    type YourData = { ... }
    const unknownObject: mixed = ...
    const validatedObject: YourTarget = (reify: Type<YourData>).assert(unknownObject)

See https://github.com/codemix/flow-runtime/issues/150 and https://codemix.github.io/flow-runtime/#/docs/type-refinemen...

The `reify` marker from flow-runtime and the accompanying Babel plugin will produce a runtime type object that can validate your data at runtime according to your Flow types.


> 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

This is spot on. I prefer type-driven development. But maintaining these typings is costly. Maintaining the definitions upstream is also difficult. GOing back to my redux / router example. There was one class they were going over again and again. Because it had a number of permutations and didn't meld well with a type system.


I found the TypeScript contributors very responsive on GitHub issues. Maybe I'm just lucky?

I just submitted a bug[0] on Jan 5 and it got fixed on Jan 9.

Another bug[1] from a couple years ago was submitted Aug 4 and fixed Aug 5.

I'm pretty satisfied ;)

[0]: https://github.com/Microsoft/TypeScript/issues/21031

[1]: https://github.com/Microsoft/TypeScript/issues/4155


Also in the flow camp for our project, I originally chose it over typescript because it seemed to fit in the react ecosystem better, but I've found that typescript has way more typings in their type repo than flow, and sometimes I wonder if the grass is greener on the other side.

I don't mind the "types on an untyped language" situation, it reminds me of C (the original). Any project that gets big enough eventually picks up a few `void*`s.


Well, typescript has a full time team complete with a project manager and all.

Flow is more like a side project that is completely getting out of hand. typescript stole all of flow's best ideas and they have way more man-days to apply to problems.

These projects are hardcore. Being able to strap a type system on top of the monstruosity that is JS is very hard. On top of bug catching (this may not even be the major factor for me) it adds invaluable type documentation that remains in sync with the code to the projet; you just can't load everything in your head, models and all.


> Flow is more like a side project that is completely getting out of hand.

Flow is used on all of Facebook's modern internal front-end code, and has a dedicated team maintaining it. They release major bugfixes and new features on an almost weekly cadence.

The "issues" count above is the 3rd party library definitions, which I don't think Facebook involves themselves too much in. The community for TS is larger, so therefore more issues will be found and fixed.


I disagree. I've used both Flow and Typescript for a few major projects. I was able to resolve virtually all of my Typescript issues by googling. Flow on the other hand required many github issues and most of them were ignored or unresolved. In my mind it's a no-brainer, Flow is dead and mostly unmaintained from an open-source point of view. I'm sure the Flow team is great but they only care about one consumer, the Facebook.

They should slap an unmaintained notice in their project and direct people to Typescript and save everyone a whole lot of hassle, including themselves.

That isn't to mention the third-party type definitions are completely lacking on the Flow side.

Flow is dead.


What do you disagree with, exactly? You just said, "I disagree", and then wrote a bunch of unrelated stuff.

Sorry that you had a bad experience. I've been using Flow for more than 2 years now and couldn't be happier.

What does "unmaintained" mean to you? Other than during Christmas, they release almost every single week [1].

[1] https://github.com/facebook/flow/releases


Did you use IntelliJ IDEA for kotlin? If not you're missing a giant part of the experience and ease-of-use.


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


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?)


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


Have you seen this related project: https://github.com/fuselabs/jsxtyper


Thank you for this. I have a slightly tangential question, can you point to some resources on the approach you used for this codemod? I see you used what seem to be native TS transforms. I've used a badly patched up jscodeshift and tscodeshift but they leave much to be desired.


Would you suggest this to someone who has (pretty much) never used TypeScript? Case is, I am going to rewrite a project and this would be quite an interesting addition!


Thank you for making this!

I've done this conversion by hand many times and I'll certainly try your program for the next untyped component that I want to import.



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.


If you're using VSCode it's super easy to try it out quickly:

https://marketplace.visualstudio.com/items?itemName=mohsen1....


I just tried the extension on this file[0] and it didn't create the Props :(

[0]: https://raw.githubusercontent.com/s-yadav/react-number-forma...


Will look into it. Large files shouldn't be a problem.


I'd urge your to consider the huge time investment with converting a large web application to TS.

It cannot be understated how much effort will be put into it. Any moderately sized application with take months of human-hours to get completely switched over.

You'll be wrestling with third-party libraries with meager documentation on how to use with TS, lots of googling to understand how to get the compiler to not complain, and a new build system that has its own idiosyncrasies.


Typescirpt suppots mixed .js and .ts projects. You can even typecheck things based on jsdoc doc comments.

https://github.com/Microsoft/TypeScript/wiki/Type-Checking-J...

I really like typescript. I'm not a static typing fanatic like a lot of people are these days, I prefer the optional annotations approach. You can set the slider to be as loose or as strict as you want, which is amazing. One thing I've just discovered is you can write types like this

    type one_to_five = 1 | 2 | 3 | 4 | 5
And it just bloody works.

I wish there was a decent REPL for it though. And no, the node REPL or anything based on it is not decent.


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


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'.


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.


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.


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).


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?


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.


No, since leaving Microsoft I've been doing everything on a Mac via VS Code.


You might find one of the JSON to Typescript type converters handy, i.e. https://shakyshane.github.io/json-ts/


There's also https://transform.now.sh/, which can handle a bunch of related transformations as well.


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.


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?


Can also confirm. Recently a convert and it's a breeze. It makes for more maintainable code, ultimately, and has even cleaned up some of my poorer JS habits.

Also, for those who get caught up rewriting types for existing libraries, I recommend you check this library first:

https://github.com/DefinitelyTyped/DefinitelyTyped


> You can take an incremental approach and add type annotations as you need them

Most definitely. We've added type safety to new features in our legacy codebase. It's very seamless.


> 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.


- 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...


The one time I think, "oof I really would have liked types here" is when I begin digging deep through a stack of calls to understand what values I should expect and are valid. This hurt me in Python too until I began using type hinting, which in my opinion is the best of both worlds: documenting types but not forcefully enforcing typing.


You just think you don't miss types but I guarantee you are doing a lot more manual work without types than with them, starting with refactorings which you must now supervise since it's pretty much impossible to guarantee the correctness of an automatic refactoring in the absence of type annotations.


Being able to 'find all references' of a variable, do a safe global rename, and 'go to definition' saves an immense amount of time.

Not to mention preventing tons of run-time bugs which saves a ton of times having to figure out.


I'm actually really happy to hear someone call it a "no-brainer". That's an indication that it's likely a good fit at any scale. I was always concerned that it was too much at smaller scales.

I will create the world's ~first~ millionth to-do app to experiment.


Even though I'm someone who doesn't reach for TS by choice (have had to use it for a couple of projects) I would add that even in a small or simple app, if you ever work with abstractions or wrapped values, you'll quickly feel the benefits of having types.


I think the bigger leap is between having a transpiler and not having one.

If you are already using babel for example, you can have it compile Typescript (basically strip away all the type annotations). At that point typescript is like an optional set of javascript features.

Also the typescript compiler is very flexible, in terms of what it enforces. You can vary it from being really lax to pretty strict.

You can use babel to do the transpilation, then have the typescript compiler run off to the side doing typechecks / providing your editor with code completion.


I'm going to against the other responders and say in our case, it wasn't worth it, and we ended up ripping out Flow from our large application.

I'll preface by saying we didn't start the project with Flow but tried to add it after-the-fact.

We ran into a ton of problems with Flow itself -- posting issues that went unanswered; flow server would regularly crash or spike our dev machines to 100% CPU. We ran into problems with third-party type definitions either being completely wrong or missing entirely. I spent weeks of work trying to get Flow to work properly.

On top of all that effort, what did we get? It caught a few runtime errors (cannot find X of undefined, X might be null but isn't checked). It was nice to see the types on our action and API payloads. Autocomplete was nice.

When we add all of those things up I'm not sure it saved the amount of effort put into converting a project to Flow ... and we ended up dropping it completely because of its continued maintenance requirements.

I'm not saying that there isn't a benefit to TS or that other teams haven't used it to great benefit but it really cannot be understated how much effort it takes to get it right. There are a lot of ways to do it wrong and there are ton of articles that will lead you in the wrong direction. From getting the build system right, to third-party definitions being out-of-date, to googling around for hours to figure it all out, it is a big time investment. Every project that is brought into your repo needs to be typed to see the full benefit.


Just don't worry about typing every single piece of code in your application. Some patterns are just plain difficult/impossible to type properly. Don't try to re-architect pieces of code to type-check fully (I did that for a while, definitely a waste of time).

The low-hanging fruit of automatically inferred typed alone is great. Even adding `//@ts-check` to JavaScript code has proved helpful.


You don't have to commit to a big up-front effort. You can take an incremental approach and add type annotations as you need them.

Also, I'm not sure how adding type annotations results in over-engineered solutions. Types are just little sanity checks you spread around your code to help the compiler and linters to catch inconsistencies. You shouldn't have to re-engineer everything.


My understanding is that now I have to also manage type definitions. It ends up being more code in my files and more files.

I'm a big fan of keeping files as minimal and simple as possible. I virtually "count" the number of language concepts that exist, and try to keep it as low as possible. Makes it easy for other developers to on-board and for me to re-on-board.


you don't actually have to manage type definitions for your own code (unless you're referring to typing parameter/return values), just things that you eg. fetch from the backend. those can be trivially generated by a tool from sample json or you can generate it all from things like OpenAPI.


You don't have to do anything. Just drop TypeScript in as a replacement for babel. Whenever you find yourself wondering if a type annotation or definition would help, then do it. Leave it optional; no commitment required.


If you haven't worked with types before, you should pull the trigger. I say this because the real issue will be whether you like working in typed code or not. If you learn you do (as I did, unexpectedly) you'll probably find yourself more productive _in general_ with it, and using it on projects of all sizes.


Try cloning this small boilerplate[0] and open with VS Code. I think you'll quickly see how powerful TypeScript is, even on a small project. Feel free to browse my repos as I have several real-world TypeScript apps.

[0]: https://github.com/styfle/react-server-example-tsx


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...


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)


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.


The React bindings for TS are quite good--I used them every day, and they're solid.

As for a ground-up approach, the bindings for ReasonML-react show how much effort it takes to have strong functional typing for React: https://github.com/reasonml/reason-react

I believe that there will be an effort to rewrite React in ReasonML in the future by core members. The goal is the leverage the power of Reason to obviate some of the weird parts of the current React internals. /shrug


Mobx is built with typescript. https://github.com/mobxjs/mobx


To be fair, mobx is more of a not-anything-like-react-like library.

Disclaimer: I like mobx


Not React, but he has a React library as well, but not written in TypeScript.


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


"Redux for babies" sounds like an insult.

It reminds me of this Nathan For You episode:

https://www.youtube.com/watch?v=BNuuiydKlI0


Looks like a nice library, but I'm not sold on the name


Not "duckling"?


React is built with Flow. Since Flow and TS achieve the same thing, I'm not sure a React-like library based on TS would bring anything new.


I have looked at Flow. I have to admit, I am biased toward good-looking code. Unless you use something like LightScript[0], Flow's syntax is not as clean or straightforward as that of TS.

Edit: I just took another look. I thought parameters had to be annotated via block comments (that's how you have to do it if using CoffeeScript 2). I was wrong.

[0] http://www.lightscript.org/


The following example written in TS works in Flow too:

  type MyComponentProps = {
    prop1: string;
    prop2?: number;
  }

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

  class MyComponent extends Component<MyComponentProps, MyComponentState> {
Same syntax.

Also, not sure how this could be more straightforward.


Thank you. I edited my comment after looking at the Flow website. My incorrect understanding came from seeing the atrocious "block comment Flow annotations" in CoffeeScript 2 (an otherwise adorable language) and thinking that was how you had to specify parameter types with Flow.


Why would the type system need to be tightly coupled with the view library? Mithril works well with TS without having been designed specifically for it.


It doesn't HAVE to, but usually libraries designed with a JS mindset don't lend themselves to type safety very well (JS coders like their magic strings and very dynamic types). Somehow React still managed pretty decently in that area whereas vueJS is a catastrophe.


I'd be interested to know how many DefinitelyTyped contributors agree with the "usually" part. My impression is that problems specifying types for existing libraries are the exception rather than the rule.


Many non-trivial libs are typed improperly, even when they can be done right. There's massive abuse of "any" type the moment anything gets semi-challenging. Also, a non-trivial amount of type definitions don't work in strict mode, which make things worse.

Anything involving complicated higher order functions (like lodash/ramda's curry), or having a single method that can be used in various ways that don't fit well with TS' overloading mechanisms are often done wrong or poorly. Flow is a bit better at this, but the techniques it provides are not always well known, so the type definitions aren't that much better.


Well, there are over 10,000 occurrences of 'any' (which effectively gives up on type checking) in the DefinitelyTyped repository:

https://github.com/DefinitelyTyped/DefinitelyTyped/search?q=...


It's true it's easier now that typescript has richer types (nullable, mapped, etc)


Nerv is a React alternative that's been built with TypeScript. Check it out: https://github.com/NervJS/nerv



Glimmer.js faster and more elegant than react. https://github.com/glimmerjs


I used Ember for almost 2 years. My experience was mostly good (see my comment regarding Ember Data--which apparently has no counterpart for React), but it enforces breaking things up into separate files a little too stringently. Routes, Controllers (at least until Components can safely replace them), Components, Templates, and Helpers (even for the most trivial operations which, IMO, are OK to sometimes include in the view).

Not to mention Ember does not use standard ES6 classes yet.

You can scrap most of Ember and just use Glimmer Components, but then all you have is a View layer, so you are not much better off than you are using React. And you __still__ have to use separate template files and helper functions.


This is a side-topic, but I recently attended a Yehuda Katz talk about glimmer. It sounds great. I'm personally really fond of ClojureScript. Glimmer seems to be very much tied to its own tooling and ecosystem. Do you think it would be possible to target glimmer from a functional programming language like ClojureScript or Reason without jumping through a ton of hoops?


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.


You might be interested in this: https://github.com/gcanti/io-ts and many related projects by Giulio.


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

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


There's also very similar project at https://github.com/pelotom/runtypes that our company uses. Don't have enough experience with it yet to say which is better, io-ts on runtypes.


quicktype (https://app.quicktype.io/) can generate TypeScript types from JSON, Schema, and GraphQL, and it also emits a runtime type representation to do dynamic typechecking. Perhaps this isn't exactly what you're looking for but you could easily modify it to generate whatever code you'd like. We have an experimental Handlebar-based templating feature to make customizing the generated code easier.


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.


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


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).


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;
    }

?


Why is lyft in the title?


It's their repo.


[flagged]


Whoa got any data to back up that claim? Cause otherwise it seems like an ad hominem attack.


I have FactoryFactory in there. You can't call that low quality ;) :D

I agree though, I'll write it differently today


sounds like someone failed a lyft interview


Shrug. I work at Uber and I find this project interesting, even though we're adopting Flow.

Haters gonna hate. If code quality is an issue, contribute, fork or gtfo. Be nice. Etc. Etc. Can we move on now?


[flagged]


The GP was an uncivil swipe, but this is a bannable offense. We'll let you off this time, but not if you do it again.

Instead, please read https://news.ycombinator.com/newsguidelines.html and take the spirit of this site to heart: civil, substantive comments or please don't post.


Wow, this grudge runs deep.

Did a Lyft engineer kill your dog?


jesus, grow up.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: