Skip to content
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 in REPL #1158

Closed
kitsonk opened this issue Nov 5, 2018 · 13 comments
Closed

TypeScript support in REPL #1158

kitsonk opened this issue Nov 5, 2018 · 13 comments
Assignees
Labels
feat new feature (which has been agreed to/accepted) repl related to the Read-Eval-Print-Loop functionality of Deno
Milestone

Comments

@kitsonk
Copy link
Contributor

kitsonk commented Nov 5, 2018

PR #998 provides a REPL for Deno, but only supports plain JavaScript. It needs to support TypeScript as well.

I was thinking about the approach and am writing up a couple ideas. ts-node provides a REPL and in looking at how they accomplish it seems like a reasonably logical approach to attempt with Deno. In order to support that, I think we need to do the following:

  • Create a Deno Compiler API that takes in a source code and optionally previous output code, returning any new lines and any diagnostics. Maybe something like this:
    incrementalCompile(sourceCode: SourceCode, previousOutput?: OutputCode): { diagnostics: ts.Diagnostic[], outputCode: OutputCode, additionalCode: OutputCode);
    Note that the compiler.configure() in [WIP] Configure compiler with tsconfig.json #1136 will likely be need as well to allow the REPL to change the configuration, which it will need to do. We might have to modify it so it actually allows some changes that we wouldn't normally allow.
  • The REPL keeps the "context" of the source code, appending lines to this context, and compiling the code incrementally.
  • The REPL then evals the incremental lines, (but not the full output code) or outputs diagnostics.

The reason it needs to work this way, is that in some cases, the TypeScript will output something higher up (like when it emits helpers) and those need to be evaled.

Things like imports and async are going to be complex, I would recommend we aim for an MVP and then figure out how to go from there.

cc: @bartlomieju

@bartlomieju
Copy link
Member

bartlomieju commented Nov 6, 2018

Thanks for opening the issue @kitsonk. Compiler extensions were my questions to you. I'll take a look at ts-node and start hacking around.

EDIT: typo

@kitsonk
Copy link
Contributor Author

kitsonk commented Jan 22, 2020

Just a couple of points on this based on some recent conversations:

  • We have been doing some refactors of the compiler, and @bartlomieju is going to experiment a bit with some other changes in keeping the compiler "running" after execution and see what impact it makes. This in theory would allow efficient transpiling of TypeScript within Deno.
  • The process in ts-node is like this:
    • ts-node keeps a script in memory and appends to it with every statement added in the REPL.
    • The entire script is transpiled in the compiler.
    • ts-node diffs the previous output from the current output and then runs whatever the diff is in v8.
  • ts-node doesn't use the language services to do incremental compilation, it uses the full compile program. I am not sure which would be most efficient. It certainly would be easier to just do the compile, and if we persist and update the old program state, then I suspect it would be fairly quick.
  • There is a decent amount of discussion between module and script modes with V8. TLA would work in modules, but not in scripts without some re-writing of the input. I think we would have to keep it as a script, because modules need to be closed so they can be properly evaluated, where scripts can continue to have statements added to them.

@cknight
Copy link
Contributor

cknight commented Jan 27, 2020

No idea about the practicality of this suggestion, but could you have the best of both worlds by having the typescript support enabled through a flag? In other words, one REPL (e.g. loaded via deno) for javascript and another for Typescript (e.g. loaded via deno -ts).

@kitsonk
Copy link
Contributor Author

kitsonk commented Jan 27, 2020

Yeah, feels like we will need some sort of flag, because it is a bit heavyweight to have TS always on in the REPL. Technically, it shouldn't be too hard.

@ry
Copy link
Member

ry commented Jan 27, 2020

Striping types should be easy enough - i kinda think v8 should be able to do it... I wonder if they would accept a patch to add an API for that...

@kitsonk
Copy link
Contributor Author

kitsonk commented Jan 27, 2020

So, Babel does that. The TS team worked with Babel to ensure the lexer could "ignore" TS. So the logic is there and I suspect documented in some fashion. It is more than just types though, as there are some TypeScript syntax which has a functional emit and isn't erasable (which they avoid like the plague now), specifically enum and const enum come to mind. (There are also some legacy things like import foo = require("foo"); too, which is valid TS but not anywhere close to valid JS).

@vp2177
Copy link

vp2177 commented Feb 19, 2020

It would be useful to be able to experiment in the repl and see type errors, supporting that would need more than just stripping types though.

@ry
Copy link
Member

ry commented Feb 24, 2020

I just left this comment #3760 (comment)

There are many things we can do to improve the REPL without introducing the TS compiler. We should do those things first (e.g. improve inspect, tab completion). Once we're on par with Node's REPL, we can start looking into how to go beyond that by using typescript.

@bartlomieju bartlomieju added the repl related to the Read-Eval-Print-Loop functionality of Deno label Feb 24, 2020
@kitsonk kitsonk added the feat new feature (which has been agreed to/accepted) label Nov 5, 2020
@kitsonk
Copy link
Contributor Author

kitsonk commented Nov 5, 2020

Now that we have fairly frictionless access to swc and there are other reasons we might want to use swc in REPL to parse JavaScript, we could support TypeScript without type checking in the REPL.

Thoughts @caspervonb?

@caspervonb
Copy link
Contributor

Preferably we would also add better completion if we're integrating TypeScript support but we can just do stripping as a first pass, I'll get back to this once I'm done with code coverage.

@mcarifio
Copy link

While you're sorting this out, perhaps you might want to augment the banner for deno repl to something like:

$ deno
Deno 1.9.0, repl js
exit using ctrl+d or close()
> 

If you opt for the --ts flag, then:

$ deno repl --ts
Deno 1.9.0, repl ts
exit using ctrl+d or close()
> 

I think it's reasonable to want to "think this through" and to attend to other repl things first (e.g. better completion or tabs). But I was surprised when I added some simple typing to the deno repl (e.g. let x:number = 1) and got an error message. Since I'm also learning ts, I thought my statement was misformed. For now I'll use ts-node to experiment with ts constructs in a repl. It's just nice to focus my learning on one tool rather than several. In js land, that never seems to be true.

@caspervonb
Copy link
Contributor

Took a stab at this recently, will be landing soon just need to wrap up some other patches.

@dsherret
Copy link
Member

Closing now that #10934 is merged.

See #11078 and #8652 for further developments or please open a new issue for any other typescript related REPL feature requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat new feature (which has been agreed to/accepted) repl related to the Read-Eval-Print-Loop functionality of Deno
Projects
None yet
Development

No branches or pull requests

8 participants