You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I would like the performance benefits of static typing to be taken into consideration, while deciding the shape of this proposal. There is a very interesting talk of Tzvetan Mikov available under this address on youtube, which shows that JavaScript could be even 20x faster if types of variables and parameters are strict and known. It's possible that this compiler will work out very well and in a few years, we might be considering whether some parts of it could be implemented in V8/JSC/SpiderMonkey. We might want to declare primitive types on parameters & variables, just so JS engines can apply various optimizations before any code is executed and let those parts run significantly faster. This will no longer be possible if the current proposal passes, because by then, web will be filled with JS code contaning meaningless type annotations that are not verified at runtime.
We might want to declare primitive types on parameters & variables, just so JS engines can apply various optimizations before any code is executed and let those parts run significantly faster. This will no longer be possible if the current proposal passes, because by then, web will be filled with JS code contaning meaningless type annotations that are not verified at runtime.
I'm not sure I understand how the conclusion follows from the premise here.
I read this as an implication that it's virtually impossible to design a type annotation syntax today so that it would be compatible with, and useful to, the optimizing compiler of tomorrow. But I fail to see why that would that be the case.
https://www.assemblyscript.org/ comes to mind as tangentially related: an example of adapting a pre-existing type syntax (TS-based) for a static compiler (to WASM, not native engine's IR, but still).
Most implementers, however, have implied this would be a very large performance hit.
Also curious about why this would be the case. My naive intuition is that more type info available in the source = easier to make better optimizations. Any links to explanations why it would do the opposite? Is it just a matter of parsing type info outweighing massively the optimizations made possible by the presence of the type info, or is the current generation of optimizations somehow dependent on dynamic typing?
The talk is very interesting, but even the presenter concedes, this is not for your whole application. I also find it interesting that they only showed primitives. That is usually the simple part of validating types at runtime. How do you validate objects? Or array of objects?
If we want to keep a dynamic version of JS, where you can just create object literals, how do we validate those types when we pass them to functions that require a specific declared type (or even worse a specific memory layout for that object). We can think of different language with different constraints that would look like ES that could make this work, but it would not be ES anymore.
Either way, I don't think the current version of types as comments precludes something like static hermes from existing. They could benefit from adding their own type comments to augment what TS / Flow already do.
I am guessing that performance hit could be coming from process of parsing object types(so interface, type & object notation) and verifying that they match the actual objects that are being used in runtime. For a very simple cases like let a: number = 5;, I think JS engines could get a performance boost, but I am just speculating based on what I have heard from the talk.
Now if that's the case, and declaring primitive types like number or even something more precise like int32 could bring very high performance benefits, I think it would be very much worth to add it to the language. The : syntax could be used to declare those sound types, for example:
Now, if the current proposal passes and npm is already filled with lots of JS files in which types don't match what is declared(asd("555", 33)), we will not be able to introduce sound types with : syntax without breaking existing code(for example because "555" + 33 + 5 now returns 555335 and sound types would make it throw an exception).
Most implementers, however, have implied this would be a very large performance hit.
A hit where? Like if it's just parsing, well this really suggests the problem is that the binary ast proposal should be revived.
For runtime types, obviously work would needed to be done to support it everywhere, but there's no obvious reason for performance losses except at the boundary between typed and untyped (but in a fully typed codebase, this boundary would often not exist anyway).
Reacted by Danny Kim, Ziad El Khoury Hanna, AⱯ, Elnar Khisamov, ExE Boss, tocque and Míla Kuchta
That's an interesting discussion everyone is having, I also have an idea:
I. Background and Motivation
JavaScript, as a widely used programming language, is renowned for its flexibility and dynamism. However, in high-performance scenarios such as intensive computations, its performance is often affected by factors like type coercion and dynamic parsing. To enhance JavaScript's performance in these scenarios while retaining its inherent advantages, we propose the introduction of a new compilation mode: "use compilation".
II. Overview of the Compilation Mode
The "use compilation" mode is an optional compilation mode, similar to the existing "use strict" strict mode. In this mode, type changes are not allowed, and the type is fixed based on the first declaration or assignment. This type immutability enables the code to be pre-compiled into bytecode before execution, thereby significantly improving execution efficiency.
III. Expected Outcomes
Performance Enhancement: By pre-compiling and enforcing type immutability, the runtime overhead of type checking and parsing is reduced, leading to a substantial performance boost in scenarios like intensive computations.
Broad Applicability: As an optional mode, developers can choose to use it based on project requirements, thereby preserving JavaScript's dynamic features while also providing a path for performance optimization.
In 2015, Google's V8 team experimented with a proposal to implement a new JS mode that they called "Strong Mode," intending to use types to improve site performance. Google canceled the experiment in failure. "In the end we had to give up on this one."
That's an interesting discussion everyone is having, I also have an idea:
I. Background and Motivation JavaScript, as a widely used programming language, is renowned for its flexibility and dynamism. However, in high-performance scenarios such as intensive computations, its performance is often affected by factors like type coercion and dynamic parsing. To enhance JavaScript's performance in these scenarios while retaining its inherent advantages, we propose the introduction of a new compilation mode: "use compilation".
II. Overview of the Compilation Mode The "use compilation" mode is an optional compilation mode, similar to the existing "use strict" strict mode. In this mode, type changes are not allowed, and the type is fixed based on the first declaration or assignment. This type immutability enables the code to be pre-compiled into bytecode before execution, thereby significantly improving execution efficiency.
III. Expected Outcomes Performance Enhancement: By pre-compiling and enforcing type immutability, the runtime overhead of type checking and parsing is reduced, leading to a substantial performance boost in scenarios like intensive computations. Broad Applicability: As an optional mode, developers can choose to use it based on project requirements, thereby preserving JavaScript's dynamic features while also providing a path for performance optimization.
So why not directly use "use strict" to enable type annotations in strict mode, which can avoid introducing a new mode while also making strict mode live up to its name.
The linked post doesn't really argue against that strongly against types; verbatim from the article:
TYPES?
Not all is lost. We continue to investigate the addition of types to V8. And in fact, typing may bring some of the benefits of strong mode for lower cost.
However, the strong mode experience, as well as a number of other recent developments (e.g. scientific evaluations of the potential cost of sound gradual typing, more troublesome features in the ES pipeline, but also the advent of WebAssembly changing the premise for evolving JavaScript) will probably have us readjust our design goals. In particular, we no longer believe that requiring type soundness by default can ever work successfully in JavaScript. It may still be possible to provide sound types as an opt-in, though. But more on this at some other time.
The larger failure of strong mode as mentioned in the post was strong-mode classes, especially their interop with existing classes. (And even then, there is still appetite for classes similar to strong mode given the structs proposal has a lot of the same restrictions as strong mode classes had).
While I'm sure there is absolutely no chance of a full typescript-like type system for JS like some people might expect from such a proposal, given the existence of things like hidden classes and general successes of WebAssembly's type system it's not clear to me why a simpler type system that is more similar to engines existing type systems is not a viable way to add types to JS.
The larger failure of strong mode as mentioned in the post was strong-mode classes, especially their interop with existing classes. (And even then, there is still appetite for classes similar to strong mode given the structs proposal has a lot of the same restrictions as strong mode classes had).
While I'm sure there is absolutely no chance of a full typescript-like type system for JS like some people might expect from such a proposal, given the existence of things like hidden classes and general successes of WebAssembly's type system it's not clear to me why a simpler type system that is more similar to engines existing type systems is not a viable way to add types to JS.
In another post, someone commented that under the tc39 system architecture, changes to the JavaScript standard require the agreement of all committee members (JavaScript engine implementers). If any one of them opposes, the proposal cannot move to the next stage.
Existing rule makers indicate that currently, all changes cannot break forward compatibility.
These two rules make it extremely difficult for new proposals.
Existing rule makers indicate that currently, all changes cannot break forward compatibility.
I think you mean backwards compatibility (i.e. existing things don't break), and yes that is an absolute must, but that doesn't prohibit some opt-in design for types. Like it might as simple as adding a type annotation turns on typing for a given function:
// existence of `param: type` makes parameter typed, and opts in the behaviourfunctionadd(x: number,y: number): number{returnx+y;}constv=add("foo","bar");// TypeError
This wouldn't change the behaviour of existing code, as existing code doesn't have such annotations it would be unchanged.
Adding type annotations will not break the compatibility of existing code. What I mean is that in strict mode, type annotations should be mandatory rather than optional. --- Of course, in sloppy mode, type annotations should certainly be optional rather than mandatory.
I would like the performance benefits of static typing to be taken into consideration, while deciding the shape of this proposal. There is a very interesting talk of Tzvetan Mikov available under this address on youtube, which shows that JavaScript could be even 20x faster if types of variables and parameters are strict and known. It's possible that this compiler will work out very well and in a few years, we might be considering whether some parts of it could be implemented in V8/JSC/SpiderMonkey. We might want to declare primitive types on parameters & variables, just so JS engines can apply various optimizations before any code is executed and let those parts run significantly faster. This will no longer be possible if the current proposal passes, because by then, web will be filled with JS code contaning meaningless type annotations that are not verified at runtime.
I completely agree with the points raised by @NiedziolkaMichal. To address this exact concern, I’ve been developing a proposal called hinted.js. It moves away from "Types as Comments" toward "Speculative Metadata"—treating type annotations as promises that the engine can use for zero-check machine code and fixed-width memory allocation.
A Performance-First Hinting System
Instead of erasable metadata, the engine treats specific hints (like int 4, bit, or str N) as a contract. The developer guarantees the data shape, and the engine optimizes storage without the overhead of speculative bailing or hidden class checks.
Fixed-Width Primitives:let x: int 4 or let y: bit allow the engine to allocate raw registers or bit-packed buffers immediately.
Defined Overflows: To keep execution "zero-check," the system mandates silent wrapping (for int) and truncation (for str), mirroring the behavior of high-performance TypedArrays.
Variable-Centric Allocation: Hints are applied at declaration and argument definition, allowing the engine to treat the "receiving bucket" as a fixed-size slot regardless of the source of the data.
By providing these direct memory allocation hints, we can achieve the "near-C" speeds while maintaining JavaScript's existing ergonomics. I believe this path offers a significantly higher ROI for the parser's effort than the current erasure-only proposal.
Why would your hinted.js proposal succeed when strong mode failed?
I don't know if this specific proposal would work, but I'd like to mention as I already pointed out that in the update on strong mode, typing wasn't ruled out, the bigger problems were with other features (like class-integration):
It may still be possible to provide sound types as an opt-in, though
Whether there is engine appetite or not is another question, given I suppose the argument would be "well just use WebAssembly" in such cases. Though it is weird that in many cases WASM-to-DOM optimization has still been on a per-API basis, and in non-engine-optimized cases going all in on WASM can be a performance regression which is unfortunate.
Why would your hinted.js proposal succeed when strong mode failed?
The primary reason Strong Mode failed was its reliance on runtime enforcement. It attempted to improve performance by restricting language features and throwing exceptions when those restrictions were violated, resulted in a "policing" overhead that often negated the performance gains and created a brittle environment, code would crash instead of bailing out.
hinted.js operates on a fundamentally different architectural principle, Pre-allocate without Validation.
Unlike Strong Mode, which added runtime checks to ensure "strength," hinted.js removes them. By providing a memory hint, the developer enters a contract where the engine allocates a fixed-size slot. There is no overhead spent verifying the data; the engine simply maps the value to the hinted layout.
Strong Mode was prone to runtime failures. In contrast, hinted.js utilizes standardized silent behaviors, specifically integer wrapping and string truncation—to ensure that even if a "promise" is broken, the execution remains continuous and the memory footprint remains constant.
Strong Mode was an all-or-nothing. It created compatibility issues between "strong" and "sloppy" modules. hinted.js is applied at the variable and argument declaration level, allowing for high-performance "hot paths" to exist alongside standard dynamic JavaScript.
I don't think that's accurate - it failed because type-related errors in production were vanishingly rare. In other words, "the types are wrong" is not an actual problem in practice.
Your interpretation of the failure of strong mode does not align with the actual failure statement. Strong-mode hot paths coexisting with standard dynamic JS was one of the main causes of failure. The Chrome team specifically discussed trying to get your idea to work:
Locking down classes: This was our biggest hope and the biggest failure. One of the main motivations for strong mode was the desire to restrict classes to behave more as in conventional languages, such that they can be implemented more efficiently. The design consisted of a combination of making classes less mutable, restricting the uses of super and this in constructors, and most importantly, sealing instances. The constructor restrictions were an issue already, but the sealing idea fell apart entirely! The main problem here was the interoperability with weak classes: we need to allow inheriting strong from weak classes and vice versa (or even alternating inheritance chains), because ruling that out would severely limit the utility of strong mode. But we could not find a semantics that would work without breaking either weak parent classes or weak child classes. In the end we had to give up on this one.
@dfabulich
I appreciate the technical context. My point is that the Chrome team's 'Sealing' failed because it was Instance-Level. They tried to lock the Object itself, which broke when 'Weak' code touched it.
hinted.js avoids this by being Variable-Level. We aren't locking the object's soul; we are defining a Fixed Lens for that specific reference. By using Standardized Silent Failure (wrapping/truncation), we ensure the 'Weak' code never breaks the 'Strong' view—the engine just ignores or casts the data at the variable boundary. This localizes the optimization and prevents the 'Inheritance Trap' that sank the experiment.
Activity
ljharb commentedon Jan 14, 2024
Most implementers, however, have implied this would be a very large performance hit.
egasimus commentedon Jan 15, 2024
I'm not sure I understand how the conclusion follows from the premise here.
I read this as an implication that it's virtually impossible to design a type annotation syntax today so that it would be compatible with, and useful to, the optimizing compiler of tomorrow. But I fail to see why that would that be the case.
https://www.assemblyscript.org/ comes to mind as tangentially related: an example of adapting a pre-existing type syntax (TS-based) for a static compiler (to WASM, not native engine's IR, but still).
egasimus commentedon Jan 15, 2024
Also curious about why this would be the case. My naive intuition is that more type info available in the source = easier to make better optimizations. Any links to explanations why it would do the opposite? Is it just a matter of parsing type info outweighing massively the optimizations made possible by the presence of the type info, or is the current generation of optimizations somehow dependent on dynamic typing?
dragomirtitian commentedon Jan 15, 2024
@egasimus
The talk is very interesting, but even the presenter concedes, this is not for your whole application. I also find it interesting that they only showed primitives. That is usually the simple part of validating types at runtime. How do you validate objects? Or array of objects?
If we want to keep a dynamic version of JS, where you can just create object literals, how do we validate those types when we pass them to functions that require a specific declared type (or even worse a specific memory layout for that object). We can think of different language with different constraints that would look like ES that could make this work, but it would not be ES anymore.
Either way, I don't think the current version of types as comments precludes something like static hermes from existing. They could benefit from adding their own type comments to augment what TS / Flow already do.
NiedziolkaMichal commentedon Jan 15, 2024
I am guessing that performance hit could be coming from process of parsing object types(so
interface,type& object notation) and verifying that they match the actual objects that are being used in runtime. For a very simple cases likelet a: number = 5;, I think JS engines could get a performance boost, but I am just speculating based on what I have heard from the talk.Now if that's the case, and declaring primitive types like
numberor even something more precise likeint32could bring very high performance benefits, I think it would be very much worth to add it to the language. The:syntax could be used to declare those sound types, for example:Now, if the current proposal passes and npm is already filled with lots of JS files in which types don't match what is declared(
asd("555", 33)), we will not be able to introduce sound types with:syntax without breaking existing code(for example because"555" + 33 + 5now returns555335and sound types would make it throw an exception).egasimus commentedon Jan 15, 2024
Now I see what you mean, thanks for elaborating!
Jamesernator commentedon Jan 30, 2024
A hit where? Like if it's just parsing, well this really suggests the problem is that the binary ast proposal should be revived.
For runtime types, obviously work would needed to be done to support it everywhere, but there's no obvious reason for performance losses except at the boundary between typed and untyped (but in a fully typed codebase, this boundary would often not exist anyway).
yxdtg commentedon Apr 1, 2025
That's an interesting discussion everyone is having, I also have an idea:
I. Background and Motivation
JavaScript, as a widely used programming language, is renowned for its flexibility and dynamism. However, in high-performance scenarios such as intensive computations, its performance is often affected by factors like type coercion and dynamic parsing. To enhance JavaScript's performance in these scenarios while retaining its inherent advantages, we propose the introduction of a new compilation mode: "use compilation".
II. Overview of the Compilation Mode
The "use compilation" mode is an optional compilation mode, similar to the existing "use strict" strict mode. In this mode, type changes are not allowed, and the type is fixed based on the first declaration or assignment. This type immutability enables the code to be pre-compiled into bytecode before execution, thereby significantly improving execution efficiency.
III. Expected Outcomes
Performance Enhancement: By pre-compiling and enforcing type immutability, the runtime overhead of type checking and parsing is reduced, leading to a substantial performance boost in scenarios like intensive computations.
Broad Applicability: As an optional mode, developers can choose to use it based on project requirements, thereby preserving JavaScript's dynamic features while also providing a path for performance optimization.
dfabulich commentedon Apr 1, 2025
From the readme:
cers000 commentedon Sep 15, 2025
So why not directly use "use strict" to enable type annotations in strict mode, which can avoid introducing a new mode while also making strict mode live up to its name.
dfabulich commentedon Sep 15, 2025
Did you click the links I posted above to Strong Mode? And how they canceled the experiment in failure?
That's why not.
Jamesernator commentedon Sep 16, 2025
The linked post doesn't really argue against that strongly against types; verbatim from the article:
The larger failure of strong mode as mentioned in the post was strong-mode classes, especially their interop with existing classes. (And even then, there is still appetite for classes similar to strong mode given the structs proposal has a lot of the same restrictions as strong mode classes had).
While I'm sure there is absolutely no chance of a full typescript-like type system for JS like some people might expect from such a proposal, given the existence of things like hidden classes and general successes of WebAssembly's type system it's not clear to me why a simpler type system that is more similar to engines existing type systems is not a viable way to add types to JS.
cers000 commentedon Sep 16, 2025
In another post, someone commented that under the tc39 system architecture, changes to the JavaScript standard require the agreement of all committee members (JavaScript engine implementers). If any one of them opposes, the proposal cannot move to the next stage.
Existing rule makers indicate that currently, all changes cannot break forward compatibility.
These two rules make it extremely difficult for new proposals.
Jamesernator commentedon Sep 16, 2025
I think you mean backwards compatibility (i.e. existing things don't break), and yes that is an absolute must, but that doesn't prohibit some opt-in design for types. Like it might as simple as adding a type annotation turns on typing for a given function:
This wouldn't change the behaviour of existing code, as existing code doesn't have such annotations it would be unchanged.
cers000 commentedon Sep 16, 2025
Adding type annotations will not break the compatibility of existing code. What I mean is that in strict mode, type annotations should be mandatory rather than optional. --- Of course, in sloppy mode, type annotations should certainly be optional rather than mandatory.
dfabulich commentedon Sep 16, 2025
What would happen to existing code in strict mode that doesn’t have type annotations?
ljharb commentedon Sep 16, 2025
Making them mandatory is never an option exactly because existing code must remain valid forever.
Gokul-Gireesh commentedon Mar 12, 2026
I completely agree with the points raised by @NiedziolkaMichal. To address this exact concern, I’ve been developing a proposal called hinted.js. It moves away from "Types as Comments" toward "Speculative Metadata"—treating type annotations as promises that the engine can use for zero-check machine code and fixed-width memory allocation.
A Performance-First Hinting System
Instead of erasable metadata, the engine treats specific hints (like
int 4,bit, orstr N) as a contract. The developer guarantees the data shape, and the engine optimizes storage without the overhead of speculative bailing or hidden class checks.let x: int 4orlet y: bitallow the engine to allocate raw registers or bit-packed buffers immediately.int) and truncation (forstr), mirroring the behavior of high-performanceTypedArrays.By providing these direct memory allocation hints, we can achieve the "near-C" speeds while maintaining JavaScript's existing ergonomics. I believe this path offers a significantly higher ROI for the parser's effort than the current erasure-only proposal.
Full Proposal: hinted.js
dfabulich commentedon Mar 12, 2026
Why would your
hinted.jsproposal succeed when strong mode failed?Jamesernator commentedon Mar 12, 2026
I don't know if this specific proposal would work, but I'd like to mention as I already pointed out that in the update on strong mode, typing wasn't ruled out, the bigger problems were with other features (like class-integration):
Whether there is engine appetite or not is another question, given I suppose the argument would be "well just use WebAssembly" in such cases. Though it is weird that in many cases WASM-to-DOM optimization has still been on a per-API basis, and in non-engine-optimized cases going all in on WASM can be a performance regression which is unfortunate.
Gokul-Gireesh commentedon Mar 12, 2026
The primary reason Strong Mode failed was its reliance on runtime enforcement. It attempted to improve performance by restricting language features and throwing exceptions when those restrictions were violated, resulted in a "policing" overhead that often negated the performance gains and created a brittle environment, code would crash instead of bailing out.
hinted.js operates on a fundamentally different architectural principle, Pre-allocate without Validation.
Unlike Strong Mode, which added runtime checks to ensure "strength," hinted.js removes them. By providing a memory hint, the developer enters a contract where the engine allocates a fixed-size slot. There is no overhead spent verifying the data; the engine simply maps the value to the hinted layout.
Strong Mode was prone to runtime failures. In contrast, hinted.js utilizes standardized silent behaviors, specifically integer wrapping and string truncation—to ensure that even if a "promise" is broken, the execution remains continuous and the memory footprint remains constant.
Strong Mode was an all-or-nothing. It created compatibility issues between "strong" and "sloppy" modules. hinted.js is applied at the variable and argument declaration level, allowing for high-performance "hot paths" to exist alongside standard dynamic JavaScript.
ljharb commentedon Mar 12, 2026
I don't think that's accurate - it failed because type-related errors in production were vanishingly rare. In other words, "the types are wrong" is not an actual problem in practice.
dfabulich commentedon Mar 12, 2026
@Gokul-Gireesh Reread https://groups.google.com/g/strengthen-js/c/ojj3TDxbHpQ
Your interpretation of the failure of strong mode does not align with the actual failure statement. Strong-mode hot paths coexisting with standard dynamic JS was one of the main causes of failure. The Chrome team specifically discussed trying to get your idea to work:
Gokul-Gireesh commentedon Mar 13, 2026
@dfabulich
I appreciate the technical context. My point is that the Chrome team's 'Sealing' failed because it was Instance-Level. They tried to lock the Object itself, which broke when 'Weak' code touched it.
hinted.js avoids this by being Variable-Level. We aren't locking the object's soul; we are defining a Fixed Lens for that specific reference. By using Standardized Silent Failure (wrapping/truncation), we ensure the 'Weak' code never breaks the 'Strong' view—the engine just ignores or casts the data at the variable boundary. This localizes the optimization and prevents the 'Inheritance Trap' that sank the experiment.