Deno: TypeScript support in REPL

Created on 5 Nov 2018  路  10Comments  路  Source: denoland/deno

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:
    ts incrementalCompile(sourceCode: SourceCode, previousOutput?: OutputCode): { diagnostics: ts.Diagnostic[], outputCode: OutputCode, additionalCode: OutputCode);
    Note that the compiler.configure() in #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

feat repl

Most helpful comment

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.

All 10 comments

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

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.

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).

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.

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...

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).

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.

I just left this comment https://github.com/denoland/deno/pull/3760#issuecomment-590472390

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.

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?

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JosephAkayesi picture JosephAkayesi  路  3Comments

CruxCv picture CruxCv  路  3Comments

ry picture ry  路  3Comments

kitsonk picture kitsonk  路  3Comments

sh7dm picture sh7dm  路  3Comments