Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.52k stars 2.87k forks source link

Implement TypeScript in New Expensify #16665

Closed roryabraham closed 1 month ago

roryabraham commented 1 year ago

Proposal: Utilize TypeScript to reduce bugs in NewDot

๐Ÿ“„ Link to the design doc

docs.google.com/document/d/1LNcgYeYyovQ88gNjLIgBqBReLtbLAbxeAbna9QKxeAQ/edit#

๐Ÿ–‡๏ธ Other links

Strategy

Our strategic roadmap for the next couple years is Reunification โ€“ moving all of our existing users from OldDot to NewDot, and itโ€™s going to look like a completely new product. During this transition period, thereโ€™s an increased risk for churn, and stability of the platform is more important than ever. Any lines of defense between our customers and bad code will pay dividends during any tumultuous times to come.

Problem

JavaScript has been very popular for front-end development for a long time, and over the years it has evolved with new developer-friendly features that make it easier to GSD. Overall, itโ€™s pretty great. However, it is still plagued by one fundamental problem: runtime errors stemming from incorrect types. This common class of problem leads to bugs, ranging in severity from showing weird things on the screen to crashing the whole app.

While there are many bugs that can be caused by incorrect types, the most common example of a runtime type safety error is Cannot access property X of undefined. A quick GitHub search reveals that over the last couple years we have introduced hundreds of this type of bug into the NewDot codebase, each of them stemming from this same root cause โ€“ attempting to access a property on a variable whose value is undefined. When this occurs, the app crashes.

Solution

Let's commit to adopting TypeScript in New Expensify, an awesome superset of JavaScript that gives us the benefits of using a compiled language like C++! That way, type errors can be caught at compile-time instead of run-time, and a whole class of common bugs will be eliminated from our product. #BugZero here we come.

Furthermore, letโ€™s engage the near-limitless capacity of our open-source community to do it in parallel to our existing roadmap, without pausing any other feature development in the meantime.

Tasks

AndrewGable commented 1 year ago

I have read and reviewed this Design Doc!

hayata-suenaga commented 1 year ago

Is this a super high priority? It looks like it was created with a Daily tag for everyone to review in one day, which normally we reserve for things that are impacting the next couple waves. @danielrvidal

This issue has the "daily" label because this project involves external vendors who already started working on some tasks. Migration is one of those projects that don't have a clear deadline. But they're also the kind of projects that benefit from a short lifespan.

As this design dos is rather short, we thought we could justify requesting reviews with the daily label ๐Ÿ™‡

flodnv commented 1 year ago

I have read and reviewed this Design Doc!

johnmlee101 commented 1 year ago

I have read and reviewed this Design Doc!

puneetlath commented 1 year ago

I have read and reviewed this Design Doc!

maddylewis commented 1 year ago

I have read and reviewed this Design Doc!

NickTooker commented 1 year ago

I have read and reviewed this Design Doc!

danielrvidal commented 1 year ago

I have read and reviewed this Design Doc!

PauloGasparSv commented 1 year ago

I have read and reviewed this Design Doc!

twisterdotcom commented 1 year ago

I have read and reviewed this Design Doc!

roryabraham commented 1 year ago

We've seen good activity and detailed reviews have been moving along nicely.

hayata-suenaga commented 1 year ago

The detailed review is done ๐ŸŽ‰

Here are the next steps.

For the assignment and division of tasks and tracking of subtasks of these four tasks, we delegate them to SWM and CallStack. Please communicate with each other to divide responsibilities ๐Ÿ™‡ @fabioh8010 @blazejkustra

For each of these four tasks, I created a GH issue. We'll eventually put these issues inside a GH Project we'll create for the TypeScript migration. Please report any progress in the respective issue.

I provided rough deadlines for each task. These are more like guidelines rather than strict deadlines. Please provide your own estimate on the completion time of the task in the issue itself.

1. Define TypeScript guidelines

A rough overview of the guideline is in the design doc. Let's create the first version of the guideline in app/contributingGuides/TYPESCRIPT_STYLE.md Let's add succinct code examples as needed. Create sub-files if necessary to divide the guideline into sections.

Please write the guideline following conventions widely used in open-source communities and also those already used in other guidelines in App (ex. usage of shall, should, or must).

2. Prepare libraries for migration

Create type definitions for react-native-onyx and expensify-common. Until these definitions are complete, we cannot move to the migration of App.

3. Prepare the GH project and issues

@fabioh8010 is already testing GitHub's Project feature and figuring out how to create migration issues.

4. Setup App for TypeScript

melvin-bot[bot] commented 1 year ago

@neil-marcellini, @roryabraham, @hayata-suenaga Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

neil-marcellini commented 1 year ago

The PR to set up the app for typescript is under review and I just finished my review. I'm eager to keep helping out mostly by reviewing.

roryabraham commented 1 year ago

The main PR to integrate TypeScript toolchain into E/App is in review. Exciting!

neil-marcellini commented 1 year ago

I started reviewing the Typescript guidelines PR today.

blazejkustra commented 1 year ago

PR with type definitions for expensify-common is ready here. Please check it out! ๐Ÿ‘€

hayata-suenaga commented 1 year ago

With amazing work by @fabioh8010 and @blazejkustra, we're on a good track ๐Ÿš€ There are the latest updates!

Next Steps

hayata-suenaga commented 1 year ago

The TypeScript GH Project now has the public visibility

melvin-bot[bot] commented 1 year ago

@neil-marcellini, @roryabraham, @hayata-suenaga Whoops! This issue is 2 days overdue. Let's get this updated quick!

hayata-suenaga commented 1 year ago

A new PR for TS guidelines was created, and I expect the review to be finished by the end of this week.

@fabioh8010 is working on creating type definition files for react-native-onyx

script for creating GH migration issues is ready

We should start thinking about typing core data. The PoC PR for this is already made here by @thiagobrez.

cc: @fabioh8010 @blazejkustra

neil-marcellini commented 1 year ago

We're planning to merge the expensify-common PR by EOD and the App set up PR by EOW.

hayata-suenaga commented 1 year ago
cead22 commented 1 year ago

I have read and reviewed this Design Doc!

hayata-suenaga commented 1 year ago

Current progress

hayata-suenaga commented 1 year ago

Requested internal engineers' review on the core data PR in NewDot here.

roryabraham commented 1 year ago

Progress is ongoing. We were discussing a related change (that can happen separately from the main TS migration) in these threads:

I personally think the most significant decisions that are being made are how we are typing react-native-onyx, and I sadly am not up-to-date on the latest there

hayata-suenaga commented 1 year ago

the most significant decisions that are being made are how we are typing react-native-onyx, and I sadly am not up-to-date on the latest there

@roryabraham

The draft PR for creating definition files in Onyx is going here.

hayata-suenaga commented 1 year ago

End of week update

The following PRs are waiting for the migration to start

Action items for next week

roryabraham commented 1 year ago

Had a sync with @hayata-suenaga today. The main action item at the moment is getting all the reviews in for this big PR

hayata-suenaga commented 1 year ago

Mid week update

mountiny commented 1 year ago

@roryabraham , @mountiny, and @neil-marcellini do you have any idea how we can make sure that engineers are reminded to update the TS type definitions for Onyx data when the backend data shapes change?

I am not sure, maybe some action/ webhook analyzing the code changes

@blazejkustra @fabioh8010 any recommendations?

blazejkustra commented 1 year ago

@roryabraham , @mountiny, and @neil-marcellini do you have any idea how we can make sure that engineers are reminded to update the TS type definitions for Onyx data when the backend data shapes change?

I am not sure, maybe some action/ webhook analyzing the code changes

@blazejkustra @fabioh8010 any recommendations?

So, there are couple of ways to do it:

  1. Custom-Built Codegen: Although we don't use GraphQL on the backend, we can draw some inspiration from GraphQL. The concept is to implement a code generator, which could automatically generate TS type definitions based on our backend data shape. Writing a custom codegen for a PHP backend might be a challenging task. Such approach might require some investment of time and resources initially but has the potential to make the backend-frontend sync easier in the longer run.
  2. Publicly Defined Schema: Similar approach, publicly define the schema and utilize it at both ends - backend and frontend. JSON Schema could be utilized for that. To ensure that backend is in sync with the schema, input and output of every request would be validated with the schema. On the frontend we could either create types manually and validate incoming data in the runtime or use json-schema-to-typescript to generate TS types automatically.
  3. New Development Process: New step in the review process, whenever backend data shapes are changed require a change on the frontend. That could be backend developer responsibility to make sure that changes are reflected in the types on frontend. Couple ideas:
    • Additional checkbox in checklist on the backend PR
    • Automation that checks data shapes on each commit on the backend, if needed require a frontend change (not sure if that's possible because I don't have access to the backend)
    • Runtime validation in the App, so that types defined in the App are compared with what we get from the API (Zod could be useful for that)
hayata-suenaga commented 1 year ago

@mountiny I was asking how we can change the internal process (add new checklist item, etc) for Web-E PRs so that engineers are reminded to change the type definition of the backend data changes.

should we just edit the PR template for Web-E? Should we also add a checklist for Auth, too?

mountiny commented 1 year ago

@hayata-suenaga I am curious though if checklist will be enough to check for this. I think we can start with it and see if we will have people ignoring it

hayata-suenaga commented 1 year ago

@mountiny yes I think the option #2 @blazejkustra suggested is something we want to consider down the line

but I'm thinking something we can implement right now that at least do something toward ensuring type consistency between front end and backend.

I created an internal issue to update templates for Web-E and Auth PRs, I gonna make PRs for them today

roryabraham commented 1 year ago

@roryabraham , @mountiny, and @neil-marcellini do you have any idea how we can make sure that engineers are reminded to update the TS type definitions for Onyx data when the backend data shapes change?

I think we should punt this problem (or maybe rumor of a problem) for now and just focus on getting TypeScript built out in a leaner V1. Long-term I love the idea of having a shared, versioned schema for Onyx used by both the front-end and back-end to automate the compatibility between layers. But I feel strongly that we're getting ahead of ourselves here.

We don't currently have anything to ensure Onyx schemas are compatible in the front-end and back-end, and it's been working mostly ok. The amount of type safety we'll get in the front-end alone will be a huge win.

FWIW, if someone's updating something in Onyx in PHP, they'll probably try to access that property in E/App, and notice that the type is wrong. I kind of think that's enough to start.

roryabraham commented 1 year ago

That said, if we're going to do anything I agree with @mountiny's suggestion that we can add a webhook comment on API PRs like:

I noticed that you changed some code that has to do with Onyx. Did you adjust the Onyx schema? If so, make sure you adjust the corresponding Onyx type declaration in E/App.

We could probably do that pretty easily but I don't think it should be a top priority for this project.

hayata-suenaga commented 1 year ago

Will merge the guideline PR this afternoon and post the announcement

neil-marcellini commented 1 year ago

I'm continuing to review the PRs to type Onyx data in App and to add type declarations for Onyx. Both are very close I think.

hayata-suenaga commented 1 year ago

Mid-week update

Once the above two PRs are merged, we can execute this script to create migration GH issues and officially kick off the TS migration.

Side notes

I realized there are additional libraries being developed right now at Expensify for App

We probably have to rewrite them in TypeScript or write TS definitions for them at some point. Just a note. I'll keep track of the related project and update here.

blazejkustra commented 1 year ago

The review for https://github.com/blazejkustra/App/pull/1 progresses a lot thanks to @neil-marcellini. What is the time estimate for this PR to be merged?

@hayata-suenaga There is a TODO list in the description of the PR explaining whatโ€™s left. Currently the only blocker is react-native-onyx PR, once it's merged, Iโ€™ll install the typed version of Onyx and the PR should be ready.

hayata-suenaga commented 1 year ago

Merge Schedule

App TS Setup PR ->

Onyx + TS PR -> Core Onxy Data in App

hayata-suenaga commented 1 year ago

Weekly Update

neil-marcellini commented 1 year ago

Heads up, I'm going to be OOO Monday and Tuesday next week so please don't let me be a blocker for anything while I'm out.

roryabraham commented 1 year ago

Update from @blazejkustra today here

blazejkustra commented 1 year ago

Mid-week update

After react-native-onyx & Onyx type core data PRs are merged, we can proceed to phase 2 of Typescript migration! ๐Ÿš€

hayata-suenaga commented 1 year ago

I didn't do end of week update last week ๐Ÿ˜ญ but it's already time for...

Mid-week update

Once the App Setup PR is merged, then we're officially and finally ready to start migration.

We first have to run this script (sorry internal link) to create GH migration issues in the TS migration project (this one should be public link).

If I remember correctly, we will start migration from leaf files and the first phase of the migration is conducted only by CallStack and SWM engineers. Checking with @blazejkustra and @fabioh8010 how these expert agencies plan to coordinate with each other in allocating issues.

hayata-suenaga commented 1 year ago

End of week update

Once the App Setup PR is merged, then we're officially and finally ready to start migration.

Next week, we gonna run this PHP script (internal link) with the updated CSV file that @fabioh8010 is going to provide to create migration issues.

In the initial phase of the migration:

SWM and CallStack are going to coordinate with each other to assign issues to themselves.

We have to make sure that engineers from these organizations have permissions to assign themselves to issues on GH.

Additional Note: @blazejkustra and @fabioh8010 are OOO on next Monday and Tuesday

hayata-suenaga commented 1 year ago

Quick Update

Here is the latest update in the issue that is blocking @blazejkustra's Onyx core data App PR. The blocking PR hasn't been merged yet.

Once the above PR is merged, we gonna also merge this PR that adds a new checklist item in the backend PRs (Web-E and Auth) to encourage engineers to update the Onyx Data TS definitions if they change data shape.

Once @fabioh8010 returns from OOO, we can run this PHP script (internal link) to create GH issues for migration tasks with the updated CSV file that @fabioh8010 is going to provide us.

Also, we were originally planning to de-structure component props before the migration starts, but the --fix for eslint didn't work well with the react/destructuring-assignment rule, and I could't de-structure props in batch. So we have to manually de-structure components when migrating to TS.

I believe this rule is not currently turned on for TS files. So I gonna open a PR for it so that ESLint warns if we forget destructure props when migrating.