loading...
Cover image for why deno want remove typescript from your internal code?

why deno want remove typescript from your internal code?

buttercubz profile image Erick Sosa Garcia ・4 min read

after it was announced that typing will be removed from the deno kernel, many thought it meant that deno no longer natively executed typescript. In this post I'm going to try to explain what it means to remove typescript from the deno core.

first of all, take it easy! deno will continue to support typescript.

this is ryan's reply in an issue on github

"" I saw that this design doc was being discussed more widely. Most people don't have the context to understand this narrow technical document - it is only applicable to a very particular, very technical situation in the internals of Deno. This is not at all a reflection on the usefulness of TypeScript in general. It's not a discussion about any publicly visible interface in Deno. Deno, of course, will support TypeScript forever. A website or server written in TypeScript is a very very different type of program than Deno - maybe much more so than novice programmers can appreciate - very little of Deno is written in TypeScript. The target audience is the 5 to 10 people who work on this particular internal system. Please don't draw any broader conclusions. ""

the problems

one of the problems that drives to remove the internal typescript is the compilation time of the cjs/js files.
explain the following:

incremental compile time when changing files in cli/js takes minutes. This is crushingly slow and painful to modify.

performance issues:

The typescript organization/structure that we're using in cli/js is creating runtime performance problems. As an example, we recently realized that we're unable to to get TS to generate a class with the name "Header" because it shadows the declaration in our d.ts file. So instead we name the class "HeaderImpl" and assign it to "window.Header". But that creates the problem that "Header.name" has the wrong value. So we're forced to add unnecessary runtime code

Object.defineProperty(HeaderImpl, "name", { value: "Header" });

to fix "Header.name". Who knows if this kicks Header out of some optimization path in V8. The optimal thing is to generate "class Header { ... }" anything less suggests a fundamental flaw in the design.
TypeScript is supposed to be helping us organize code, but one could claim it has the opposite effect. For example, we have two independent Body classes https://github.com/denoland/deno/issues/4748. This is difficult to have visibility into because of the complexity involved with generating the runtime code.
Ideally we would have a system where two Body classes would be obviously wrong.

Our internal code and runtime TS declarations must already be manually kept in sync. TSC isn't helping us to generate the d.ts files - it was too much overhead and complexity when we attempted it before.

We have two independent TS compiler hosts: one for the internal Deno code in //deno_typescript/compiler_main.js and another other for external user code in cli/js/compiler/. These two hosts have similar goals - they seek to modify TSC to operate on Deno-style imports (e.g. with file extensions). The //deno_typescript is used at build-time while the cli/js/compiler/ is used at runtime.

solution

this is the solution proposed by the deno team:

A radical solution is to remove all build-time TS type checking and bundling for internal code. We would move ALL runtime code into a single big file cli/rt.js. This file would be dropped directly into V8 at build-time to create the snapshot. The corresponding cli/rt.d.ts would contain the type definitions and documentation.

In this setup it will be possible to write code like class Header { } and clearly understand what is provided and executed in the runtime.

At first glance the idea of having a 10k line javascript file sounds unappealing. But I think compared to the current system, this will allow new contributors to quickly understand how Deno bootstraps itself.

Build-time complexity and performance is obviously better with this setup. Of course we will still need to do a snapshot, but we will not have to build a special TSIsolate to first execute tsc.

Runtime complexity and performance is strictly better with this setup. It will be very clear if we have multiple definitions of a class. We will be able to see all code that is being executed clearly. We will be able to analyze and step through the code during debugging without worrying about additional source map complexity.

It's important to explicitly note that Deno user code will still be in typescript and type checked. We will have tests to make sure the code works as intended against cli/rt.d.ts

The compiler worker will need its own separate cli/compiler.js file. It does not need a corresponding d.ts. One drawback of this approach is that it will be difficult to share code between the compiler worker and the runtime itself.

conclusion

As ry explained, this is a problem that is not for the general public that uses deno, it is a problem of the team that develops deno, this would help improve the development of deno, and perhaps improve its general performance, and it is good not to draw conclusions without understanding in the context in which they are developed.

I hope the information has been useful to you, the sources where I got this information will be below. ¡Gracias por leer!

resources

Discussion

pic
Editor guide