Skip to content

[POC] Incremental switch to Typescript#9517

Closed
rosskevin wants to merge 17 commits into
mui:v1-betafrom
alienfast:ts-switch
Closed

[POC] Incremental switch to Typescript#9517
rosskevin wants to merge 17 commits into
mui:v1-betafrom
alienfast:ts-switch

Conversation

@rosskevin
Copy link
Copy Markdown
Contributor

@rosskevin rosskevin commented Dec 16, 2017

The goal

The goal of this PR is to as minimally as possible get to the typescript tool chain to allow us to incrementally convert to typescript.

This POC (as-is) proves

  • Typescript can be used to interpret ts, tsx, and js files
  • Typescript can run a TS spec with js source, specifically Paper.spec.tsx

Sticky transition points

  1. modules with module.exports = warning are different in TS, they need to use import deepmerge = require('deepmerge') and this workaround can only be applied in a .ts file. In an effort to minimize this POC and keep the filesjs for the moment - I created a folder /utils/ts-import-workaround with relevant re-exports. As soon as the files are moved from js to ts, this is totally unnecessary
  2. eslint for the above issue, and eslint in general. We can momentarily use eslint-disable-line on the above imports so that eslint is happy with the js. As (or if) we move to TS, we should consider moving to tslint instead of eslint. Smarter type aware linting with much of the same rules are available, though not as extensive as eslint. There are more options here

Advantages

In the minimized amount of work during this process I uncovered several TS definition bugs in our code. These were trivial but nonetheless - doing something like this will firm up our use of TS definitions and/or ts files themselves. And, of course, this also gives us a way to move to fully typed TS at our own pace.

Next steps

If we decide to move ahead, move through the rest of the typescript errors in the project which are:

  • remove flow from remaining files - it is not valid js and therefore not valid ts
  • fix imports
  • add ts-loader to webpack (ts-loader first then babel-loader)

When removing flow on utility files, it might be just as easy to swap them to ts at that point and convert the flow types.

@oliviertassinari
Copy link
Copy Markdown
Member

+546 −29,580

@rosskevin Maybe we should removeflow-typed folder in a different PR? GitHub makes it very hard to see what changed.

@rosskevin
Copy link
Copy Markdown
Contributor Author

I put back those files to prevent the diff. You can ignore changes in the .d.ts files - prettier was not running on those previously and now is.

@sebald
Copy link
Copy Markdown
Contributor

sebald commented Dec 16, 2017

Wow, looks like this is really happening?! 🙃 Thanks @rosskevin for starting the effort.

As @oliviertassinari already mentioned removing the flow-types in another PR would be nice. It's a bit scary to review a PR with 178 changed files.

I'll will have more time on Monday to take a look. Regarding your "sticky transition points":

  1. Isn't import * as warning from 'warning'* working for you? See: https://codesandbox.io/s/yvym9w2wj

  2. Personally, not the biggest fan of tslint, but we use it too at my company, since it is much easier to setup than eslint + typescript. If we want to use eslint while converting components to TypeScript, we could try out this: https://github.com/eslint/typescript-eslint-parser

@rosskevin
Copy link
Copy Markdown
Contributor Author

@sebald the import * as warning from 'warning'; is working now. Not sure at what stage I had that problem so I'll yank it. I already put back the flow-typed files

@rosskevin
Copy link
Copy Markdown
Contributor Author

@sebald these are the errors that require the import workaround:

TypeError: deepmerge_1.default is not a function

I tried going back on deep merge to the import as * with no luck.

@rosskevin
Copy link
Copy Markdown
Contributor Author

rosskevin commented Dec 16, 2017

I'm continuing some conversion to ts of internal code on a branch - trying to inch forward to something mergeable. When all of you are done with review, I can merge my other branch to this PR.

Comment thread src/Paper/Paper.js
import classNames from 'classnames';
import warning from 'warning';
import * as React from 'react';
import * as PropTypes from 'prop-types';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most imports from non-ES2015+ modules are effectively import namespace as, which means the module's exports plus types (if any) - import them as a single named variable. So module.exports = warning is both not a named export AND not a default export, which requires this syntax to effectively get all exports as warning.

Notice that our own imports with default exports need none of this, so as we eventually graduate to ES2015 modules we won't need these even with external modules, unless we choose to import all their types as well with that variable.

Effectively - this is valid spec javascript.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we have the allowSyntheticDefaultImports flag, that can make things like "import React from 'react'" valid

see: https://www.typescriptlang.org/docs/handbook/compiler-options.html
and: https://javascriptplayground.com/blog/2017/04/react-typescript/

I think that we need to be conservative and initially just change only the syntax that are really invalid

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowSyntheticDefaultImports flag doesn't actually change the semantics of the generated code, it just disables the error AFAIK, so this is not a good thing for libraries to do IMO. Webpack may compensate for it, but your tests running in node would fail. There's a feature coming in TypeScript 2.7 which will bring the semantics in line with Babel's however.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That has also been my experience @pelotom. Turning it on just helps find the errors quicker.

@rosskevin
Copy link
Copy Markdown
Contributor Author

rosskevin commented Dec 16, 2017

I've done the src/styles conversion - src files only. I skipped withSyles|withTheme for the moment. Need to eat.
https://github.com/alienfast/material-ui/tree/ts-switch-continued

@oliviertassinari
Copy link
Copy Markdown
Member

Question, does it make sense to try to convert one component here too?

@rosskevin
Copy link
Copy Markdown
Contributor Author

I can, but no it won't matter. I'm going to work on my continued branch to see if I can solve all TS errors and make tests run.

Comment thread tsconfig.json
"jsx": "react",
"moduleResolution": "node",
"lib": [
"es2017",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which es2017 features are required by material-ui out of curiosity? That seems like a strong requirement to impose on downstream users.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, we can reel that back in when tests run.

@rosskevin
Copy link
Copy Markdown
Contributor Author

I've got all TS errors fixed, working on tests.
https://github.com/alienfast/material-ui/tree/ts-switch-continued

If everyone is good with this, I'll merge that work here. Just be aware that the diff is mostly useless. I can also just leave this PR as-is, close it and open a new one.

@rosskevin
Copy link
Copy Markdown
Contributor Author

PR #9535 is up, and it's very close to mergeable.

@rosskevin rosskevin closed this Dec 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants