New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] First-class support for TypeScript in the Expo SDK #2164

Open
ide opened this Issue Aug 31, 2018 · 18 comments

Comments

Projects
None yet
8 participants
@ide
Copy link
Member

ide commented Aug 31, 2018

The Expo team is considering adding first-class support for TypeScript to the Expo SDK. For JS type systems (namely TS and Flow) we see a significant preference for TypeScript and in our own experience we find TypeScript to be stable, sufficiently expressive most of the time, and generally positive. We also find that standard, untyped JS works well and will continue to design APIs that work well without a type system.

Why

The primary reason for first-class support for TypeScript is that it is stable and works well without drawing too much on our attention for maintenance. The TypeScript team has done very good work creating smooth upgrade plans (e.g. upgrading from TypeScript 2.x to 3.x is quite smooth) and we've found their work to be reliable. We believe that making more parts of Expo -- in this case, TypeScript -- more reliable will make it more reliable to develop and use apps made with Expo.

Additionally, the very recently released Babel 7 supports TypeScript, which means we can continue to use Babel-based builds for Expo hopefully without introducing too much thrash or instability.

How

In practice, this proposal means that the Expo SDK would move to .ts files and the Flow type hints would be replaced by TypeScript type hints. Today, TypeScript type declarations (https://github.com/DefinitelyTyped/DefinitelyTyped) are helpfully maintained by developers in the Expo community and the Expo SDK provides Flow types; this would switch around where the Expo SDK would provide TypeScript types and the community, if someone were to step up, would maintain Flow type declarations in https://github.com/flow-typed/flow-typed. Given the history of solid work from the TypeScript team, the popularity of TypeScript amongst Expo developers, and the stability and reduced maintenance tax we expect from moving the Expo SDK to TypeScript, we believe this is a high-ROI tradeoff.

Some dependencies of the Expo SDK that aren't maintained by the Expo team, like React Native, Maps, and SVG, may not have complete or accurate type declarations so we expect to start with TypeScript's default non-strict mode, adding stricter options when possible in a forward-looking way (ex: will we be able to keep the strict option when upgrading a dependency in the future?).

Eventually, we may also provide TypeScript support in the new-project templates so it is easy for developers to work with TypeScript from the start. We will continue to design our APIs to work well without TypeScript, which we believe to be responsible, safe, and forward-looking.

Request for comments

We are looking to see how this proposal resonates with Expo developers, especially professionals building apps for business. Along with this RFC thread, we'll also talk to some developers in interviews and at conferences to gauge feedback before making a decision in the coming weeks.

@ide ide added the rfc label Aug 31, 2018

@msevestre

This comment has been minimized.

Copy link

msevestre commented Aug 31, 2018

@ide I have worked with TS and flow (TS with ionic and flow with React native) and I have to agree that the developer experience, in my opinion, is far superior with TS.

Would that mean that a new expo project would support typescript out of the box? Or is this something that the user would have to configure by hand?

Cheers,

@ide

This comment has been minimized.

Copy link
Member Author

ide commented Aug 31, 2018

Would that mean that a new expo project would support typescript out of the box? Or is this something that the user would have to configure by hand?

To start, a new Expo project wouldn't have TypeScript enabled but if you set up TypeScript, the Expo SDK would ship with .ts / .ts.d files for most of the Expo APIs. Over time, we'd provide guides and CI coverage for TypeScript. With this proposal, we'd like to support TypeScript well but not prescribe it.

@jhalborg

This comment has been minimized.

Copy link
Contributor

jhalborg commented Sep 10, 2018

This would be great! When I started out with React Native and Expo last April, I went with Flow because it seemed to have the most support in the RN environment and community. I wrote two production apps that way before switching to Typescript for everything since. It was for the same reasons you mention - stability and quality, as well as better and more tooling and community typings. I really hope this change goes through! 😄

ide added a commit that referenced this issue Sep 12, 2018

[typescript] Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Closes #2164

ide added a commit that referenced this issue Sep 14, 2018

[typescript] Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Closes #2164
@ckknight

This comment has been minimized.

Copy link

ckknight commented Sep 17, 2018

We currently have a tsc --watch running during development that builds everything in src/ and puts the compiled .js files into dist/. Our entrypoint then points to dist/App.js (instead of src/App.tsx).

I'd love for TypeScript support to be a built-in capability.

Types for Expo would be fantastic as well. DefinitelyTyped is out of date in a few areas.

@Kingles

This comment has been minimized.

Copy link

Kingles commented Sep 17, 2018

Echoing @ckknight here, as is DefinitelyTyped definitions (which have been generally great, huge thanks to the folks working to keep those up) are three major versions out of date and have led to a significant amount of headache, especially when touching edges of the built-in Expo api (some of the more esoteric Camera options, for example). Having a more-or-less guaranteed up-to-date version of the expo types would be a huge win.

@jhalborg

This comment has been minimized.

Copy link
Contributor

jhalborg commented Sep 18, 2018

@ckknight & @Kingles - You can actually use a custom transformer as examplified here and --noEmit already, but it would sure be nice to have a somewhat opinionated and supported setup from the Expo team, especially for newcomers looking to use Typescript.

@ide

This comment has been minimized.

Copy link
Member Author

ide commented Sep 18, 2018

We're working on moving parts of the Expo SDK to TypeScript in a gradual way. Not all of the SDK will be typed to begin with because it's large and there are also several parts we currently don't maintain ourselves. And we're working around some of TypeScript's rough edges but don't have solutions for all of them (ex: we need "skipLibChecks" because the react-native and isomorphic-global fetch declarations from DefinitelyTyped clash in an unfixable way AFAICT).

The contributors to the DefinitelyTyped expo declarations definitely deserve thanks and a shout out, especially @janaagaard75 and @KonstantinKai who've contributed almost half of the commits to the declarations between the two of them.

edges of the built-in Expo api (some of the more esoteric Camera options, for example)

We'd definitely like to make this more robust. Currently there's five-way fragmentation between the JS, Android module definition, iOS module definition, docs, and DefinitelyTyped declarations when all of them are intended to describe the same API and it'd be nice to start coupling their interfaces together and to work towards a fundamentally better single source of truth.

@jhalborg

This comment has been minimized.

Copy link
Contributor

jhalborg commented Sep 19, 2018

We're working on moving parts of the Expo SDK to TypeScript in a gradual way. Not all of the SDK will be typed to begin with

I don't think you need to, at least not to begin with. From a consumer point of view, all we need is

  1. First, and most importantly, a team-maintained definition file of the Expo API so that all API changes going forward are always reflected in the definitions that comes with the package, so it doesn't rely on the otherwise solid work of community members.

  2. Perhaps more/better documentation in the Expo docs about how to set up and work with a Typescript + Expo project, perhaps springing from the also great example authored by @janaagaard75

After 1. is done, you can implement Typescript in the codebase at your own pace without the community being any the wiser, except for the few of us who sometimes contribute :-)

ide added a commit that referenced this issue Sep 20, 2018

[typescript] Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Closes #2164

@ide ide self-assigned this Sep 20, 2018

@ide ide added the in progress label Sep 20, 2018

ide added a commit that referenced this issue Sep 20, 2018

[typescript] Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Starts #2164

ide added a commit that referenced this issue Sep 20, 2018

[typescript] Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Starts #2164

expbot added a commit that referenced this issue Sep 20, 2018

Preliminary migration from Flow to TypeScript
This migrates the Expo SDK umbrella package to TypeScript. The individual modules (that is, dependencies) have not been migrated to TypeScript. The TypeScript is compiled to JS, which is published to npm along with the original TypeScript files. This preserves compatibility with non-TypeScript-aware build pipelines.

Unit tests pass locally and in CI.

There are still several loose ends:

- ts-lint has some rough edges till we upgrade to Babel 7
- Several ts-ignore comments, especially around module exporting. We need to decide a consistent way to write imports/exports.
- Need to figure out how to do lazy imports (not dynamic imports, just lazy evaluation)
- Types look like "any" to the outside world because of the lazy requires we currently have. It might take a couple more SDK cycles till TS is ready to expose to developers.

Also need to update the docs for Facebook Ads and AR, both of which had API changes because of this

Starts #2164

fbshipit-source-id: 506213f
@jamesisaac

This comment has been minimized.

Copy link

jamesisaac commented Dec 27, 2018

Seems like a slightly funny direction to me for a project that's so closely tied to the React Native core (Expo even being promoted several times in the main RN docs), when React and React Native are both officially Flow codebases. Typing Expo in TS means that:

  1. Whether someone uses Flow or Typescript, by starting with a blank Expo project, they'll already be on top of a mixture of official and community typings, decreasing coherency and increasing the chances that something breaks between versions. (Given that the Typescript community is admittedly very active, surely typings for React+RN+Expo can be maintained well together in the DefinitelyTyped repo).
  2. To contribute to the RN/Expo ecosystem (where the lines are quite blurred), a developer would now need to be proficient in both TS and Flow, jumping between the two depending on what module is being worked on.

I mean, I'm sure there are arguments that, for example, Rust transpiled to JS is a more "stable and reliable" language to write projects in than TS, but obviously for the sake of consistency in the ecosystem and codebases, that wouldn't be enough of a reason to port Expo to Rust.

From what I've seen, Flow and TS each have their quirks, but have both been improving fairly fast, and converging more and more over time, now each offering an extremely similar feature set. The main divide just being around what the base ecosystem is built on top of (e.g. Facebook: React/RN/Relay -> Flow ; Angular -> TS).

I'd be interested to hear what was such a big pain point with Flow that it warranted porting the entire codebase? (And surprised that FB's Flow team haven't prioritised addressing those issues higher, given that Expo is promoted essentially as an official extension of RN).

@jamesisaac

This comment has been minimized.

Copy link

jamesisaac commented Dec 27, 2018

Ok, I see there's quite a bit of code appearing in the repo to adapt Expo to Flutter. If that's the long term goal of Expo, to be fairly backend-agnostic, with RN as just one of several supported platforms, I guess I see where you're coming from with re-evaluating the type system. My comment above was assuming that Expo was always intending to be very much a project on top of the React Native ecosystem.

@satya164

This comment has been minimized.

Copy link
Contributor

satya164 commented Dec 27, 2018

Whether someone uses Flow or Typescript, by starting with a blank Expo project, they'll already be on top of a mixture of official and community typings

That implies that even after the Expo official SDK is written in TypeScript, community typings would be maintained separately. Which seems unnecessary. Also won't they need to run npm i -D @types/expo to get the community types?

Flow and TS each have their quirks, but have both been improving fairly fast

TBH Flow's tooling hasn't improved for a long time. And it doesn't seem to improve as fast as TypeScript (or maybe the improvements aren't marketed). Flow's inference is definitely better though. Anyway, I think people will agree that TypeScript has much better tooling, editor support, and a huge number of library definitions.

BTW this tool claims to generate robust flow types from typescript definitions (I haven't used it), however, the reverse isn't possible. So it should be possible to support both without writing separate type definitions.

@jamesisaac

This comment has been minimized.

Copy link

jamesisaac commented Dec 27, 2018

That implies that even after the Expo official SDK is written in TypeScript, community typings would be maintained separately. Which seems unnecessary. Also won't they need to run npm i -D @types/expo to get the community types?

I meant that, even if Expo TS types become first party, the React/RN types will be community maintained. If Expo was still intending to be tightly tied to RN, this is just a potential point for errors, as community RN types won't be as well maintained as the official Flow ones in the RN repo (it's part of their CI to have 0 flow errors before pushing out a new release).

TBH Flow's tooling hasn't improved for a long time. And it doesn't seem to improve as fast as TypeScript (or maybe the improvements aren't marketed).

Could you give any examples of this? I hear this a lot, but when I tried TS I didn't notice any difference except better VSCode support (which makes sense, as they're both MS products). However, Flow has been doing a lot of work over the past months to build in LSP support (search "LSP"), which as far as I understand is Microsoft's protocol that will allow VSCode to use Flow in the same way it does TS.

BTW this tool claims to generate robust flow types from typescript definitions (I haven't used it), however, the reverse isn't possible. So it should be possible to support both without writing separate type definitions.

I'm skeptical this would produce particularly sound definitions. Flow just released improved built in support for HOCs, the new React ref APIs etc -- is this tool really going to be able to output code to meet these more expressive types?

Although as one idea... why not have exported Flow types as part of Expo's build step then? Would be interesting to see a real test of how well automatic conversion works in practice. And then Expo can offer official support for both with each release, without the lag of waiting for someone to update the flow-typed repo and hoping they do it properly.

@satya164

This comment has been minimized.

Copy link
Contributor

satya164 commented Dec 27, 2018

Could you give any examples of this

  • Editor support, as you mentioned. It makes a huge difference
  • No way to generate definitions from source files
  • No good way to distribute types in NPM libs. You have to copy source files to .js.flow and cannot support multiple Flow versions, which is important given things break pretty often between releases.
  • You have to use flow-typed to support multiple Flow versions, but without having an option to generate definitions, this basically means you need to write separate definitions even if your source is already in Flow
  • There are memory leaks which have been there for long time (there's an issue about it)
  • We've also experienced the server being unresponsive and restarting doesn't fix it

I'm sure Flow's developers are working in these things. But I've been using Flow for years and these are the same issues I had back then. It's mostly okay when you're using it in an app, but from library developer's point of view, it becomes a big pain point

I'm skeptical this would produce particularly sound definitions

I haven't used the tool, just pointing out that such tooling exist for TS. Even if it doesn't produce 100% correct types, it can be a good starting point to avoid rewriting them from scratch.

@jamesisaac

This comment has been minimized.

Copy link

jamesisaac commented Dec 27, 2018

  • Editor support, as you mentioned. It makes a huge difference

Hopefully LSP will help with this (I think a lot of IDEs now support it).

  • No way to generate definitions from source files
  • No good way to distribute types in NPM libs. You have to copy source files to .js.flow and cannot support multiple Flow versions, which is important given things break pretty often between releases.
  • You have to use flow-typed to support multiple Flow versions, but without having an option to generate definitions, this basically means you need to write separate definitions even if your source is already in Flow

Ah yes, good points. I don't do much library development, but if TS has a good mechanism for this I can definitely see how it would be a pain point for Flow. It's a shame that a good story for this hasn't been prioritised higher by the Flow team... would be interesting to hear if someone with connections to the team could find out if it's on their radar.

In general I just think that the competition is a good thing, and that the speed of progress we've seen over the past couple of years on both sides has been thanks to this. (Remember when Flow was first released and TS didn't even have null checking?). So I'm more in favour of helping the underdog catch up, especially when they have slightly different goals (Flow: soundness, TS: pragmatism). Completely starving it of attention, and having projects that even have a good reason to be based off Flow migrate away, I'm not sure will lead to the most productive future for type systems in JS...

@satya164

This comment has been minimized.

Copy link
Contributor

satya164 commented Dec 27, 2018

I should clarify that I don't represent Expo team and their decisons. I'm only stating my personal opinions.

In general I just think that the competition is a good thing, and that the speed of progress we've seen over the past couple of years on both sides has been thanks to this.

Agreed. I'm just getting the feeling that TS is progressing a lot faster than Flow.

@brentvatne

This comment has been minimized.

Copy link
Member

brentvatne commented Dec 27, 2018

I agree with @satya164's comments and I'm sure @ide can provide more context as well, the one thing I wanted to add here is the following chart: https://2018.stateofjs.com/javascript-flavors/overview/

Notice the portion of users that have used Flow and would not use Flow again, and compare that to TypeScript. With Expo we're trying to build a tool that makes mobile app developers happier and more productive, and I'm not convinced that Flow helps us towards that goal. TypeScript, on the other hand, has a very satisfied and rapidly growing userbase, which means that more people will be looking for tools they adopt to support it well. Competition is great, but I don't think we want to overindex our decisions on trying to encourage competition in the JS type system space. We want to pick the tool that will help people get the job done.

@brentvatne

This comment has been minimized.

Copy link
Member

brentvatne commented Dec 27, 2018

Ok, I see there's quite a bit of code appearing in the repo to adapt Expo to Flutter.

We built universal modules with the intention of making modules in the Expo SDK decoupled from each other and from the framework. Our hope for this is that we can share the code for these cross-platform API wrappers with other frameworks, and Flutter was one of the frameworks we used to test this out on.

@ide

This comment has been minimized.

Copy link
Member Author

ide commented Dec 31, 2018

Having used both in a variety of projects, TypeScript has just worked better for us overall, especially in projects with node_modules (read: pretty much anything outside of Facebook). The TypeScript team has continuously provided a stable language and set of tools and has demonstrated over several years their commitment to keeping things working well for Node and browser projects and a lot of that has carried over to Expo projects. Microsoft's support for TypeScript and VS Code has been relatively solid and after going through a few TypeScript upgrades, they've made a concerted effort to make upgrading smooth and less of a demand on our attention.

Type declarations are one of many parts of Expo and we can spend only a few percent of our time as a team on them. Even if we weren't exporting any type declarations, the Expo team would probably choose TypeScript for ourselves for several of the reasons Satya listed and more; to the extent that the Expo team's own productivity helps developers using Expo, TS helps everyone out indirectly. And given the maturity, support, and popularity of TypeScript, we can also help every TS user directly. There are downsides to adopting TypeScript over Flow like some you've mentioned and those are intentional tradeoffs we're making because other aspects of TypeScript are an overall net positive for more developers using Expo and the team working on Expo.

I don't think we want to overindex our decisions on trying to encourage competition in the JS type system space. We want to pick the tool that will help people get the job done.

Very much agree with Brent. Type systems are one of many means to an end for Expo and far from a goal here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment