-
Notifications
You must be signed in to change notification settings - Fork 483
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
Typescript support? #180
Comments
In theory it is possible to support any language. Things that would need to be done:
Not using TypeScript myself, I don't know of any similar tool for it. |
babel/babylon#523 is a big step towards making this happen. Perhaps this justifies reopening the issue? |
Has the landscape changed enough for this to be possible now? I know the Babylon parser has typescript support in the v7 beta, but not sure if the recast portion of the tooling has any support yet. |
But be really nice to make this happen. @fkling can you reopen? Also see benjamn/recast#424 |
Echoing @fkling's comment above, I've outlined what's required on the Recast side here. While I agree with @fkling about the steps, I'm generally pretty optimistic about this effort, and I would note that only the first two steps are critical to implementing TypeScript support in Recast (adding the types to Whether or not this happens ultimately depends on whether the work gets done (is that a tautology? maybe 😛 ). I'm happy to help, and I imagine @fkling is cautiously happy to provide some guidance, but I don't think either of us can commit to this project in a serious way unless we get a lot of help from the community. |
I am very interested in using jscodeshift on a TypeScript code base. I might have some learning curve on the parsing and AST stuff, but I'd be willing to help with this effort if I can! |
I used the flow parser on a typescript codebase and it actually worked very well. @blaster151 perhaps you could use it as a starting point? |
Hmm. Thanks, @ianks! I did not consider that and I will look into it! |
Same position as @blaster151 Happy to help, not so good on AST, but good on TypeScript, so if anyone can point mein the right direction, I'll make a start :) |
I made a repo containing some simple codemods to transform js{x} based react code to tsx based code. IMO, it is possible to parse react code using babylon parsor |
I copied an Angular(typescript) component in astexplorer.net and a simple codemod that reverses identifiers (https://gist.github.com/de28761373f95a0615a4ef9bc4155822/e73fd0cdec045078763954f6d2f58a434ab8f429). It works fine if the component does not contain "public" or "private" keyword but if it does following error is occurring: |
I can use the Flow parser to parse TypeScript with the exception of the casting operator (as in, myValue). (The alternate syntax ,"myValue as any", works fine - any ideas?) |
What is the concluding note here? Should we use Flow parser or parser created by @sjy? Further, can you please provide any example on how to use Flow parser for migration? |
@Phoenixmatrix has been doing some great work to add TypeScript support to both ast-types and recast: benjamn/recast#424 (comment)
This paves the way for jscodeshift to support TypeScript transforms. I wrote a quick example here: https://github.com/elliottsj/jscodeshift-transforms To make this work while those pull requests are pending, that repo has an npm dependency on This is an example transform which works on TypeScript: |
@elliottsj btw, one thing I'm not sure how jscodeshift should handle: the difference between TS and TSX. In Babylon world, as far as I understand, the difference is just if you add the jsx plugin or not. But jscodeshift is usually used to process a lot of files, and it would make sense to be able to go through ts and tsx files in one run, thus requiring to toggle the parser based on file extension or something. If your code never use |
@Phoenixmatrix that's a good point. The module.exports = function transform(fileInfo, api) {
const j = api.jscodeshift;
if (fileInfo.path.endsWith('.tsx')) {
j(fileInfo.source)
// ...
} else {
j(fileInfo.source)
// ...
}
} but
I'm not sure which of these is better. |
I'm thinking option 3 is probably what we want for @fkling what do you think? |
I tried Option 3 by upgrading beta version of babylon Also tried option 1. Updated manual-bind-to-arrow.js file, however that did not updated a single file. command: Updated file is: export default function transformer(file, api) {
const parse = source => babylon.parse(source, {
sourceType: 'module',
plugins: file.path.endsWith('.tsx') ? ['jsx', 'typescript'] : ['typescript'],
});
const j = api.jscodeshift;
var root = j(file.source);
.
.
.
if (hasChanged) {
//return transform.toSource();
return j(recast.parse(file.source, { parser: { parse } }))
}``` |
Question: Our current project runs on React 15.4.2. We identified that only following transforms are required:
However, as it is Typescript - codemode does not work. It is advisable to simply upgrade without transformation? If not then manual find and replace is the only option for now. |
@RupenAnjaria you will also need to use the work-in-progress versions of ast-types and recast, which are not yet done nor released:
You will probably also need the latest version of babylon@7, which is currently 7.0.0-beta.40. Those transforms you mentioned probably also won't work with TypeScript sources, since they're designed around a JS AST; TypeScript type annotations will likely not be preserved. TypeScript support is very much in a work-in-progress state right now, so I wouldn't recommend using it for any purpose beyond helping to test the pending ast-types and recast changes. |
so what's interesting with the way Recast works, is that it only cares about the bits you modify. So if you modify something that's in javascript, and ignore types (eg: you rename an ES6 class. The transform does nothing to the type annotations on the class, just its name), the AST node that's changing (ClassDeclaration) is the same whether you're in typescript, flow or vanilla JS. The part that is typescript specific (TSTypeParameterDeclaration) will remain untouched. That was the idea behind using Babylon as the parser for TypeScript in Recast instead of using TypeScript's parser itself. It should just work as long as everything in the file is defined in ast-types (and we think we have everything there) and anything you touch (only things you touch!) is in Recast. Since preexisting codemods only touch stuff recast supported all along, they should "just work" |
When playing around in https://github.com/elliottsj/jscodeshift-transforms, I did notice that creating a new identifier with jscodeshift/sample/reverse-identifiers.js Line 20 in 7be2557
e.g. To preserve the type annotation, I had to explicitly specify Does this mean the |
if you create a new one you'll lose stuff unless you add the properties to it. You'd need to take the existing identifier and only modify the part you care about. Maybe the identifier method is lossy when cloning the nodes? |
With `.from`, you can be explicit about which fields you want to populate, without having to deal with the positional arguments of the normal builder. See also: facebook/jscodeshift#180 (comment)
Yay! Typescript support in the latest recast, but not in the public jscodeshift facebook#180
With `.from`, you can be explicit about which fields you want to populate, without having to deal with the positional arguments of the normal builder. See also: facebook/jscodeshift#180 (comment)
This is necessary to conditionally include the 'jsx' babylon plugin when transforming a .tsx file. See also: facebook/jscodeshift#180 (comment)
I've updated my small example to use option 1 from this comment, while babylon@7 remains in beta: https://github.com/elliottsj/jscodeshift-transforms/blob/69f1d34effc22a234e41c2b2c2177f88ec8a89cd/transforms/reverse-identifiers.js#L18-L35 So this means that jscodeshift can now be used to transform TypeScript sources as long as you parse using recast directly in your transform, as shown in my example. I also have an update pending for https://astexplorer.net/ to make it possible to parse using recast + babylon@7, which will help when authoring transforms: fkling/astexplorer#301 |
What blockers remain on getting PR 301 merged over at astexplorer? The new capability would be extremely useful to me! |
@elliottsj , can we already use it? can't find anything typescript related in docs |
I'm assuming this issue is close because the maintainers don't want to support TypeScript. Well, I believe that TypeScript market share is >30% among React users. While I don't use TypeScript, maybe supporting it is important. |
@oliviertassinari it's not first class citizen, but it CAN be used with TS now. If anything, the only missing things (I think?) are documentation and possibly things to make it easier. But TS does work with it. |
@Phoenixmatrix Oh, this is great, documenting it would be perfect. I had a different feedback from @lookfirst on Material-UI. |
Docs would be amazing. I tried @elliottsj's example a few weeks ago but it didn't seem to work. |
Yeah, with @elliottsj's example I get an |
I've updated my example to be simpler; please try it out and let me know if something doesn't work: https://github.com/elliottsj/jscodeshift-typescript-example I'd be interested to hear the jscodeshift maintainers' thoughts on the level of support they'd be willing to give to TypeScript, with respect to documentation, testing, and potentially as a first-class format. i.e. without the need to define a custom const parse = source => babylon.parse(source, {
sourceType: 'module',
plugins: file.path.endsWith('.tsx') ? ['jsx', 'typescript'] : ['typescript'],
}); cc @fkling On a related note, I learned today about this project: https://github.com/square/babel-codemod It looks like they recently added TypeScript support (codemod-js/codemod#137) |
Thanks for the update @elliottsj. With the last commit the actual transform doesn't change, right? I'm getting the same result as before: Some more details:
The error is in the j(recast.parse(file.source, { parser: { parse } }))
.find(j.Identifier)
.replaceWith(
p => ({
...p.node,
name: p.node.name.split('').reverse().join('')
})
);
return "console.log('hi');"; Looking at the AST generated, it seems fine to me. |
I just tried your example @elliottsj and I'm getting the same error as @kiliancs. |
I did this in a local fork and it was sufficient for the simple codemods I needed to run: #269 |
Thanks for great job provided for implementing typescript. But it still not clear, is it possible to develop codemods using astexplorer? I saw @elliottsj PR to astexplorer project which is already merged. But looks like the trick with using babel 7 in codemod itself are not applicable in astexplorer. |
This allow using astexplorer + jscodeshift via babylon7 parser, more details there: facebook/jscodeshift#180 (comment)
I'm still seeing the |
Sorry I've neglected this thread for a while. Looks like TypeScript support was officially released today: https://github.com/facebook/jscodeshift/releases/tag/v0.6.0 I'm updating my example to use the new version, pending this fix. |
With `.from`, you can be explicit about which fields you want to populate, without having to deal with the positional arguments of the normal builder. See also: facebook/jscodeshift#180 (comment)
With `.from`, you can be explicit about which fields you want to populate, without having to deal with the positional arguments of the normal builder. See also: facebook/jscodeshift#180 (comment)
This library is awesome, but I can't use it since my codebase is in typescript. Any chance of TS support in the future? Or could you maybe point me in the direction of similar projects that work for TS?
The text was updated successfully, but these errors were encountered: