> Why not define a type system for JS in TC39 instead?
> TC39 has a tradition of programming language design which favors local, sound checks. By contrast, TypeScript's model -- which has been highly successful for JS developers -- is around non-local, best-effort checks. TypeScript-style systems are expensive to check at application startup, and would be redundant every time you run your JavaScript applications.
> Additionally, defining a type system to run directly in the browser means that improved type analyses would become breaking changes for the users of JavaScript applications, rather than for developers. This would [violate goals around web compatibility (i.e. "don't break the web")][1], so type system innovation would become near-impossible. Allowing other type systems to analyze code separately provides developers with choice, innovation, and freedom for developers to opt-out of checking at any time.
> In contrast, trying to add a full type system to JavaScript would be an enormous multi-year effort that would likely never reach consensus. This proposal recognizes that fact, and also recognizes that the community has evolved type systems that it is already happy with.
This is essentially doing that—it would allow browsers to parse and run TypeScript. What it isn't doing is actually having browsers do type checking, for good reason: the TypeScript type checker is a large and complex piece of software, so browsers would either have to incorporate it (and they're probably not excited to have a large chunk of JS code in the critical web-page-rendering path, nor would they be excited to have a critical chunk of the browser with a single implementation), or reimplement it themselves (which would be a huge amount of work, and make changes to the language much slower and more difficult).
Ya this seems like an awesome idea. Let devs run the type checking before they ship code, and then let the browsers run the code just as they would plain JavaScript, ignoring the types. If someone's going to use TypeScript they would be tye checking it first anyway, so no real need to check it again at the browser.
> JavaScript would minimally need to add syntax for things like type annotations on variables and functions (..) however, (..) parameter properties would be out of scope for this proposal
I'm not sure what that last part means, but it doesn't mean that type annotations for function parameters are out of scope, right?
Either way, a big step, congrats to the authors for finding the courage to undertake it!
Edit: no it's not [1], though I'm still not sure what it does mean.
Heh, it's funny how one can have quite a bit of experience with a language, yet remain completely ignorant of parts of it (pretty much everything related to classes, in my case). Thanks!
Well, my goal is not to know all the nooks and crannies of TS-the-language, but just to reap its benefits. There's a reason I haven't interacted with classes yet, and that same reason holds for why I'm not using Angular :)
That's a major limitation of JavaScript. For example:
// TypeScript
function add(a: number, b: number): number { return a + b; }
// tsc output (JavaScript)
function add(a, b) { return a + b; }
// (ab)use by someone using my lib without TypeScript
add("abc", "def");
Now, addition is a contrived example because it'll still work with strings, but the point is that such usage violates my code contract because the contract was deleted during compilation. It's possible to do this:
function add(a: number, b: number): number {
if (typeof a !== 'number' || typeof b !== 'number')
throw 'no';
return a + b;
}
But that's needlessly verbose, and eslint will complain about useless code. If enforceable type annotations could be added to JavaScript, that'd be a huge plus.
IMO MS should focus on making tsc faster, browsers shouldn't have this added complexity for no benefit. This would also seem to encourage shipping extra non-functional code to users. If the only benefit is in development then that could just be served by sourcemaps.
It's been shown I think that keeping JS a simple dynamic compile target has much more value and allows languages compete and evolve separately from browsers. Let us have things like ClojureScript, TypeScript, Elm etc compete & coexist on a level playing field on their own merits.
This proposal is pretty much just adding a standard specialized comment syntax to the language. Different tools can still utilize these comments in their own way. The proposed syntax is pretty on target to what the existing static type analyzers have converged on. I don’t see how it is giving an unfair advantage to one tool over another.
If anything it will lower the barrier of entry for new static type analyzers which can compete on how good their type system is, as opposed to the new language they are currently forced to create along side the type system.
The beauty of this proposal is that it would keep JS as exactly that.
Optional type annotations, packaged as a part of vanilla JS instead of requiring a build step, would be the only benefit. They'd be stripped out at runtime; the compiled JS would be identical.
The complexity / change cost: Since this would be a JS language addition, this would add complexity and churn to the JS language syntax. (There is no separate runtime / compile time in the JS model as implemented by JS browsers and tooling - except when run through JS-to-JS compilers).
The benefit: Sown by TS users or possibly some kind of of TS-lite using this subset of TS features.
Not benefiting: non-TS languages targeting the browser, like Elm, ClojureScript, ReScript, PureScript, Haxe, Nim, Kind, and <the next big language here>.
If anything, this gets vanilla JS users more comfortable with types in their JS. That seems like a win, and a good gateway to more strongly-typed languages.
Even if other languages aren’t actively benefiting, does it hurt them in any way? They wouldn’t even have to make any changes to their compilers; their compiled JS would stay just as valid.
The benefit is not to just Typescript users and advocates; the benefits are for everyone who wants more sanely developed JavaScript. Seems pretty good.
By far and away the most popular compile-to-JS language is JavaScript itself, via tools like Babel. After that, you've got Typescript, which is still basically just JavaScript with some type annotations stuck to it. It's only after that that you start getting to languages like Cjs and Elm, which have more varied semantics and treat JavaScript more like a true compile target.
My reading of that would actually be the opposite: JavaScript is a pretty poor language to target, and, for all its flaws, it's easier to stick to languages that mostly have JavaScript-like semantics and syntax than opt for a different (and potentially better) language, but have to deal with the more complex debugging processes.
I think this will be different for Wasm, which has been explicitly designed as a compilation target, but that's still getting off the ground in terms of being suitable for general usage.
The languages I listed don't really suffer from JS impedance mismatch or other major practical problems. The interop of course is still a hump from a programmer POV, a FFI to another language is always a portal to another culture.. But even there the shared object system and GC makes it much better than interop between native code languages.
WebAssembly suitability for general HLLs is possible in the far future but there don't seem to be many eager consumers. People prefer JS interop, browser API access, and builtin high performance GC and a JIT of JS that can efficiently handle dynamic constructs with advanced compiler magic. Reimplementing those in your wasm targeting compiler would be a huge effort and complexity cost, and added bloat to compiled programs, even if wasm supported it.
I don't see the point. This proposal only goes halfway and large swathes of syntax (like enums) will not be supported. So it doesn't achieve its stated goal of letting you run Typescript in the browser. The cost is making all JS engines implement the parser, raising the barrier for entry for new JS engines, and hampering innovation in the future by tying Typescript down to the slowest JS engine developer.
The solutions we already have (typescript in comments, or lightweight dev servers like vite) aren't perfect, but they don't come with the gargantuan costs of types in JS.
For better or for worse, features of TypeScript that generate code (like enums) are generally considered a mistake. I assume part of the idea here is that people would aim to target this particular subset so they can avoid compiling while in development and as such people would move away from those features. I like enums but you can get most of the same benefits with
Offtopic but I have to ask now that this came up, why do people even use enums instead of string literal type unions? The latter just seems so much simpler and more readable to me. You get the same type safety, pretty much the same or better performance, autocomplete works fine etc.
One reason I've heard is that enums allow you to do rename symbol refactoring in all use sites, but like what
How often do you need to do that? Once in a lifetime? Twice? And with string unions you can ofcourse also just rename it, TS will tell all the places that need fixing, and it'll take couple hours to go though 1000+ usages of it.
If I used enums (ButtonSize and IconSize) then that would not be possible and TypeScript would complain.
So the question is: Is that a bad thing?
And the answer depends on your domain. If you have reason to believe that in your domain people are likely to map between two incompatible namespaces, then enums could help. And string unions could let through some bugs.
In my experience that’s never been a real risk so I prefer string unions.
The other thing enums can get you is you can rename the variable without changing the values. So if your strings are persisted to the database and you don’t want to change them, but you do want them to have a slightly new meaning, you could rename the enum key, and get the new name in code, while keeping the old string value.
I hear what you're saying but I'd rather not waste even those two hours ;)
I agree with what @erikpukinskis said but I'll also add that I just like the way they read. It immediately tells me that there is a limited number of potential values that can be put in a place. If I see some arbitrary string then I have to wonder, if only briefly, if any arbitrary string can be plugged in there.
// What does addTask take? Days of the week?
// Time-sensitive identifiers like you'd see in moment.js?
// I guess I'll check the definition or mock out a call to see
addTask('Sunday', newTask)
// vs.
// Ah, it takes a day
addTask(Day.Sunday, newTask)
It's subtle and not super important but it makes me happy.
> For better or for worse, features of TypeScript that generate code (like enums) are generally considered a mistake.
Considered a mistake by whom? they are valid Typescript.
It's just creating yet another flavor of Typescript... and why straight out adopt that type syntax? Because it will please Typescript developers and Microsoft?
All for what? being able to run that flavor of typescript without having to compile typescript files into Javascript? It would change nothing to the already complex build pipelines JS developers are already mandated to use for production.
I agree with the parent, this is a bad proposal.
What Typescript should do as an alternative is better support for JSDoc type analysis. I don't use typescript language, however I do use typescript compiler.
The developers of TypeScript. TypeScript aims to avoid adding anything to the runtime as a result of the type system[1].
> It would change nothing to the already complex build pipelines JS developers are already mandated to use for production.
You're right, it wouldn't change anything when you're building for production if you're doing things right. It would mean that you don't have to repeatedly compile your code while you're developing it though.
> What Typescript should do as an alternative is better support for JSDoc type analysis.
If you read the proposal you'll see they explain why expanding JSDoc is not ideal. Personally, I wrote a lot of JSDoc back before TypeScript and now I don't want to touch the stuff. TS is much more ergonomic and expressive.
> So it doesn't achieve its stated goal of letting you run Typescript in the browser.
At risk of running afoul of HN guidelines: did you actually read the post?
The proposal does not add type checking to JavaScript. It adds type syntax. There is a huge, huge difference.
Their proposal is to implement a comment-like type syntax. These types would be totally ignored at runtime.
This isn't "run TypeScript in the browser"; this is "add syntactic sugar to vanilla JavaScript to get the development benefits of types without a build step."
Yes, JavaScript engines would have to implement a parser for this syntax. Yes, this raises the barrier to building a new JavaScript engine.
Does that mean JavaScript should add no new syntax ever again? No, of course not. So the question becomes one of cost-benefit analysis. And I think the TS team has submitted an extremely compelling argument for the benefits.
Your comment acknowledges the existing benefits of types-in-comments; think of this proposal as a significantly nicer way to write those.
In fact, this would be quite nice for TypeScript compile TO. JS engines could use the automatically generated type hints optimization, validation, reflection, etc.
>Does that mean JavaScript should add no new syntax ever again? No, of course not.
Yes? Yes. Maybe?
At least not in cases where the language can already do things adequately, and the change is just a cosmetic improvement. Annotating comments already works, changing that just to have a syntax that looks like type hinting but isn't just makes the language worse in my opinion. I'd rather they just bite the bullet and add optional type hinting, and make the syntax do what it appears to. Otherwise, the necessary complexity of typing Javascript should be kept entirely out of the language itself - including special syntax to make things easier. Deal with Typescript and its peculiarities and the build step, if that's what you want to do, and annotate types in the existing comment syntax, but Javascript is an untyped language and should be remain absolutely, even aggressively agnostic about such things.
Yes I completely understand that it's not about adding type checking in the browser.
My complaint is about adding type parsing in the browser. When I say "run typescript on the browser", I mean running code written in typescript syntax.
> This proposal only goes halfway and large swathes of syntax (like enums) will not be supported.
"Large swathes" is really overstating it. The TS philosophy has been to avoid runtime behaviour for quite a few years now, and while there are a few features that made it in back when they weren't so strict about that yet, they wouldn't have added them today and have worked to add alternatives that do not modify runtime behaviour (like literal string union types). So it goes as much "halfway" as all TS development has gone for the past few years.
why not just make JavaScript engines like node and browsers strip out TypeScript? Hide it under a flag if you want, it’s developers who are debugging who would benefit from that the most.
I mean this is a great idea, removing one more of the many many complexities in simply getting a nodejs package to browser and debugging (getting accurate source info and avoiding transpile errors are a PITA). JavaScript is an interpreted language yet 90% of the time it’s not even run interpreted. But “a proposal for Type Syntax in JavaScript” when TypeScript and JSDoc exist is just confusing and redundant.
But isn’t that what this is? Just an agreed upon way of specifying type info so browsers can be taught to ignore it instead of having to strip it at build time to produce something the browsers can parse?
This proposal is essentially a way to standardize a subset of typescript (a subset for now...).
It's Microsoft imposing their technology on the ECMA committee.
Ironically the same Microsoft that rejected ES4. We wouldn't be needing Typescript if ES4 was adopted 15 years ago...
edit: While this proposal doesn't have runtime typechecks, it's just one step toward adding runtime typechecks it isn't a stretch to think that if this passes, runtime typechecks might eventually be added to the language. ActionScript 3/JScript.net/ES4 had them, so it's perfectly possible for Javascript "with types" to add them as well.
Hey there, speaking as a champion of the proposal, the TypeScript PM, and a representative in TC39 for 6 years, we're not trying to impose anything or pressure anyone. We hope to present this proposal, and are fully open to discussion and criticism. We are committed to working with other standards representatives, working through the stage process, and not "pushing weight" around here.
I wasn't there for ES4; however, the type semantics of ES4 is a drastically differ from what's being proposed here. There is some information on the FAQ about why runtime types are a non-starter. (https://github.com/giltayar/proposal-types-as-comments/#why-...)
This comment probably won't count for much - actions speak louder than words. Hopefully we can demonstrate that we're being genuine here.
On its face this is (to me) an obvious, and obviously good, proposal in the abstract. So obvious I’m astonished it’s taken so long to materialize. I’ll leave it to the proposal and other advocacy to justify that: I’m just noting my bias for anyone who may misinterpret what follows, because I have some concerns about the details.
1. While care was obviously taken to be type system agnostic, and while TypeScript is obviously the current incumbent, I think there could be more of a sign of collaboration with Flow, Closure and Hegel.
1a. They’re notably mentioned but conspicuously no one from those projects is listed as authors/champions. This suggests to me that they weren’t (substantially) consulted in drafting the proposal, which implicitly weights the proposal’s details in TypeScript’s favor if only by inertia.
1b. There’s surprisingly little “give” in terms of the few minor differences between Flow and TypeScript. I’ll grant the potential reservation of `opaque type`, but strongly suspect that’s because opaque types are already under consideration as a TS feature.
2. Omission of certain runtime-affecting constructs is certainly pragmatic, and not omitting them almost certainly a deal breaker for the proposal. But, it’s also quite likely to fragment TypeScript, effectively deprecating those parts of the language (which I’m sure the TS team would prefer to do explicitly, but well, that’s a much heavier lift).
3. This limited subset of TS syntax almost certainly is a real superset of JS, but there are some parsing disambiguation complexities to consider, particularly for type parameters on functions as well as (if ultimately included) function overloads and bare property modifiers. This also affects runtime performance, particularly at load time which is critical.
4. Omitting JSX makes sense in the current state of the world, but does it make sense for the goals of this proposal?
4a. JSX usage outside of TS has an almost totally overlapping motivating problem: the need for a build step. It doesn’t fit the proposal now, because JSX (usually) has runtime semantics, but they’re unspecified without build time configuration.
4b. Of all things that will fracture TS, this one is irreconcilable. I’m honestly surprised it’s even being considered by anyone on the TS team.
4 (conclusion). Given 4a/4b, JSX almost certainly should be a separate proposal, but I think it should seriously be considered as a potential prerequisite.
5. The goal of rapidly evolving TS and conservatively evolving TC39 is a balance that probably can be struck, mainly because the TS team has been incredibly good at keeping their syntax and semantics aligned with standards. But baking type comments into the language with a variety of new syntax blocks that syntax from being used for other proposals. For type-only syntax that’s obviously not a huge deal, but I’m imagining a fair bit of push back on reserving, say, the colon character in function positional arguments.
Probably more I haven’t thought of. And I want to reiterate I think this is a great idea in the abstract. I want to see it succeed. If the champions or any of the TS/Flow/Closure/Hegel teams, or anyone else here thinks any (or all) of these concerns should find their way into issues on the proposal repo, please feel free to copypasta or ask me to do same.
This is absurd, if you're going to add the annotations at least have the runtime enforce them, otherwise all this is doing is saving a "compile" step for ts users specifically.
It would actually be a net negative for JS, as it would allow the syntax to be shipped on sites, and then because it isn't actually checked at runtime you will inevitably end up with sites if the engines ever do start performing type checks, and so will directly prevent them from adding it later.
So as I understand things:
* This does not actually add type checking
* It does not support the full typescript syntax, so you don't get to skip a compile stage
* This prevents JS engines actually adding type checking later, due to breaking existing content
As the FAQ of the proposal mentions (https://github.com/giltayar/proposal-types-as-comments/#FAQ), we believe adding runtime type checking would be untenable. This stems from both performance concerns and concerns around evolving whatever type-checking would be built in. For that reason, not only do we not expect engines to perform runtime checks, we would specify that these type annotations have no runtime effect.
Yes, and having spent many years working on browsers I am saying that if the annotations have no effect there will be code that ends up depending on the engine not performing those checks. At the point the syntax is burned because enforcing the checks breaks content.
I am unsure why you believe performing the checks is untenable if TS already does them? The runtime checks should be relatively cheap and in perf critical code if it turned out type checks were too expensive there are a bunch of optimizations engines can do, or the impacted functions could drop the annotations.
Adding a significant parsing surface, with the related page load perf impact, with the potential (im going to be generous) to burn the syntax, this seems like nothing but downside.
TS runs the checks at compile time and compiles to JavaScript without annotations. There is no runtime cost.
> related page load perf impact
Type annotations would likely still be stripped by minifiers, just like comments. No change.
> burn the syntax
As a dev that regularly uses TypeScript, being able to use debug builds with annotations and copy paste TypeScript into the console would save a lot of time. This would be part of larger trend of adding type annotations to dynamic languages. Python, Ruby, and other dynamic languages have blazed the trail here. There are ways to add enforcement in the future if needed, just look at 'use strict';
> > TS already does them?
> TS runs the checks at compile time and compiles to JavaScript without annotations. There is no runtime cost.
If there were performance costs this can be mitigated very easily - to be able to do compile time checks means TS is designed largely around early binding, at least in the default case. A JS engine can do this trivially.
> > related page load perf impact
> Type annotations would likely still be stripped by minifiers, just like comments. No change.
You're kidding right? You're proposing permanently changing the language, in a way that burns the type syntax for a feature that you're now saying will be stripped before a JS engine ever sees it?
> As a dev that regularly uses TypeScript, being able to use debug builds with annotations and copy paste TypeScript into the console would save a lot of time.
That sounds like a feature for your console, not the language
> This would be part of larger trend of adding type annotations to dynamic languages. Python, Ruby, and other dynamic languages have blazed the trail here.
Which enforced the types. Understand I am not opposed to the type annotations, I am opposed to this because it does not enforce those types. That means that broken content will exist, and thus burn the syntax.
> There are ways to add enforcement in the future if needed, just look at 'use strict';
Which will never happen again. As the person who implemented strict mode in JSC I can tell you that the cost of a mode switch is massive, in spec and implementation complexity. Adding another mode switch is simply not going to happen. The only reason I was ever ok with adding strict mode to javascript was the removal of the this conversion. No other part of strict mode would have warranted the cost.
I'm not one to argue, computers are fast. However, this would be a huge paradigm shift for the JavaScript ecosystem, where compile-to-JavaScript-tools like TypeScript are dominant. These tools have explicit goals to do type checking at compile time only and avoid generating anything at runtime. Runtime checking is redundant in this paradigm.
Now if you're arguing that the JS engines like V8 should be able to use type information for performance gains, I understand that wish. WebAssembly seems to be taking over the performance angle these days though, as it was designed from the start for that purpose, unlike JavaScript.
> You're kidding right? .. will be stripped before a JS engine ever sees it?
Yes. We're talking JavaScript here - billions of lines of which are compiled every year to ES5 ;-; with polyfills. Throwing away hundreds of useful features of ES2016+. This is par for the course, part of the JavaScript paradigm which this proposal understands.
> sounds like a feature for your console
That is fair, though it seems unlikely Chrome would adopt such a feature for their console without motivation. Perhaps.
> Which enforced the types
Python does not enforce types at runtime? You might be referring to something I'm not familiar with. Fired up Python 3.9. This works fine even though I'm passing strings for int.
def add(a: int, b: int):
return a + b
add("not ", "used") # 'not used'
> the cost of a mode switch is massive
But earlier you said a JS engine can do this trivially? I don't understand how this is now difficult. Ultimately, if the types are enforced, you may as well go the full monty and support TypeScript in the browser, with Deno leading the way. Stop beating the JavaScript horse and all. That's the dream. This proposal is a compromise without a doubt, with the understanding that TypeScript in the browser is politically untenable at this point.
So parsing and enforcing these types would be fine, performance-wise, but having a flag at the start of the module that says "discard types yes/no" would be a massive performance hit?
I really don't understand.
It wouldn't have to support any smaller granularity, and it wouldn't need to change parsing at all.
I already posted my concerns with this proposal but I want to add another top level comment in hopes it’ll be seen by the “why not runtime?” crowd: even if this wasn’t addressed very well in the proposal, you’re asking for too much and not enough at the same time. Instead of “JS should check types at runtime”, what I sincerely think you should ask for is “JS should optimistically optimize type annotations at runtime, and allow modules to opt into runtime type checking”. The performance implications of runtime checking every annotation is pretty much a non-starter, but helping the JIT do it for you when you ask for it? That’s a really reasonable thing to ask for! It’s even probably what JS engines will do internally if this is adopted.
I see why this seems like a reasonable thing to ask for, but JS engines tried this and failed hard a few years ago.
Google's V8 team (the team that owns Google Chrome's JS engine implementation) floated a proposal back in 2015 to implement a new JS mode that they called "Strong Mode."
The idea was that you'd opt-in with a pragma like "use strict", but this time you'd "use strong". Strong mode would include a bunch of restrictions on how you'd write your JS. For example:
- class prototypes would be frozen; it would be forbidden to add properties at runtime, or to `delete` properties from a class
- The "new" keyword would automatically Object.seal() the object
> 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.
There were other problems, too, some of which are substantially mitigated now in 2022. Maybe it's worth a try now!
…but if you're hoping to hold up type comments until "strong mode" works, well, I just don't think it's gonna work.
And so, in practice, for the next five to ten years, we're either getting something pretty much like Microsoft's "type comments" proposal, or nothing at all.
> but if you're hoping to hold up type comments until "strong mode" works, well, I just don't think it's gonna work.
I personally don’t want runtime type checking anyway[0]. Apart from my concerns[1], most of which are fairly navel gazey, I support the type comments proposal almost exactly as is.
My hope is that if others are successful asking for runtime type checking, they’re also asking for the corresponding performance problems to be addressed in tandem.
0: We already have runtime type checking: type guards. They have the advantage of being optional and explicit, which addresses performance concerns better than anything else I can think of.
How would this work with npm libraries? What if the js files I import are using a different type checker / a newer version of the type checker / invalid types?
The same way TypeScript works now. If you depend on a project with invalid/unrecognizable types, tsc will report that as a failure. (You can choose to instruct TypeScript to ignore the invalid types, or provide correct types of your own.)
I think I am against. This will just increase shipped bloat. Better to focus on TypeScript or WASM.
I would be for it if it was possible to keep TypeScript metadata somehow so I wouldn't need to create schema with Zod but with TypeScript. There was babel plugin like that for Flow and it was nice PoC and I guess similar could be done via some annotation with TSC.
Even if the usual toolchain of web development doesn't get bloated too much from an additional step of transpiling typescript to javascript, this would be a welcome addition for those that use tiny bits of javascript here and there. I have small apps where I don't minify the code because it just isn't worth the trouble. But having type checks would make it less error prone.
If you're just using tiny bits of javascript here and there, you probably don't need to type check anything, or at the very least you can do so manually. People wrote complex plugins and scripts in javascript for years without syntax additions and tooling to enforce a degree of type strictness that the language doesn't even need most of the time.
74 comments
[ 0.26 ms ] story [ 89.8 ms ] thread> Why not define a type system for JS in TC39 instead?
> TC39 has a tradition of programming language design which favors local, sound checks. By contrast, TypeScript's model -- which has been highly successful for JS developers -- is around non-local, best-effort checks. TypeScript-style systems are expensive to check at application startup, and would be redundant every time you run your JavaScript applications.
> Additionally, defining a type system to run directly in the browser means that improved type analyses would become breaking changes for the users of JavaScript applications, rather than for developers. This would [violate goals around web compatibility (i.e. "don't break the web")][1], so type system innovation would become near-impossible. Allowing other type systems to analyze code separately provides developers with choice, innovation, and freedom for developers to opt-out of checking at any time.
> In contrast, trying to add a full type system to JavaScript would be an enormous multi-year effort that would likely never reach consensus. This proposal recognizes that fact, and also recognizes that the community has evolved type systems that it is already happy with.
[1] https://github.com/tc39/how-we-work/blob/cc47a79340a773876cb...
https://github.com/giltayar/proposal-types-as-comments#shoul...
https://github.com/giltayar/proposal-types-as-comments#shoul...
The idea is to avoid hampering competition, evolution, and innovation in the type-checking space.
I'm not sure what that last part means, but it doesn't mean that type annotations for function parameters are out of scope, right?
Either way, a big step, congrats to the authors for finding the courage to undertake it!
Edit: no it's not [1], though I'm still not sure what it does mean.
[1] https://github.com/giltayar/proposal-types-as-comments#type-...
If anything it will lower the barrier of entry for new static type analyzers which can compete on how good their type system is, as opposed to the new language they are currently forced to create along side the type system.
Optional type annotations, packaged as a part of vanilla JS instead of requiring a build step, would be the only benefit. They'd be stripped out at runtime; the compiled JS would be identical.
The benefit: Sown by TS users or possibly some kind of of TS-lite using this subset of TS features.
Not benefiting: non-TS languages targeting the browser, like Elm, ClojureScript, ReScript, PureScript, Haxe, Nim, Kind, and <the next big language here>.
Why?
If anything, this gets vanilla JS users more comfortable with types in their JS. That seems like a win, and a good gateway to more strongly-typed languages.
Even if other languages aren’t actively benefiting, does it hurt them in any way? They wouldn’t even have to make any changes to their compilers; their compiled JS would stay just as valid.
The benefit is not to just Typescript users and advocates; the benefits are for everyone who wants more sanely developed JavaScript. Seems pretty good.
By far and away the most popular compile-to-JS language is JavaScript itself, via tools like Babel. After that, you've got Typescript, which is still basically just JavaScript with some type annotations stuck to it. It's only after that that you start getting to languages like Cjs and Elm, which have more varied semantics and treat JavaScript more like a true compile target.
My reading of that would actually be the opposite: JavaScript is a pretty poor language to target, and, for all its flaws, it's easier to stick to languages that mostly have JavaScript-like semantics and syntax than opt for a different (and potentially better) language, but have to deal with the more complex debugging processes.
I think this will be different for Wasm, which has been explicitly designed as a compilation target, but that's still getting off the ground in terms of being suitable for general usage.
WebAssembly suitability for general HLLs is possible in the far future but there don't seem to be many eager consumers. People prefer JS interop, browser API access, and builtin high performance GC and a JIT of JS that can efficiently handle dynamic constructs with advanced compiler magic. Reimplementing those in your wasm targeting compiler would be a huge effort and complexity cost, and added bloat to compiled programs, even if wasm supported it.
The solutions we already have (typescript in comments, or lightweight dev servers like vite) aren't perfect, but they don't come with the gargantuan costs of types in JS.
One reason I've heard is that enums allow you to do rename symbol refactoring in all use sites, but like what How often do you need to do that? Once in a lifetime? Twice? And with string unions you can ofcourse also just rename it, TS will tell all the places that need fixing, and it'll take couple hours to go though 1000+ usages of it.
Let’s say I have an Icon component with props like:
And then let’s say I have a Button component but there’s no small size: If I use string unions I can happy assign one size to another: If I used enums (ButtonSize and IconSize) then that would not be possible and TypeScript would complain.So the question is: Is that a bad thing?
And the answer depends on your domain. If you have reason to believe that in your domain people are likely to map between two incompatible namespaces, then enums could help. And string unions could let through some bugs.
In my experience that’s never been a real risk so I prefer string unions.
The other thing enums can get you is you can rename the variable without changing the values. So if your strings are persisted to the database and you don’t want to change them, but you do want them to have a slightly new meaning, you could rename the enum key, and get the new name in code, while keeping the old string value.
I agree with what @erikpukinskis said but I'll also add that I just like the way they read. It immediately tells me that there is a limited number of potential values that can be put in a place. If I see some arbitrary string then I have to wonder, if only briefly, if any arbitrary string can be plugged in there.
It's subtle and not super important but it makes me happy.Considered a mistake by whom? they are valid Typescript.
It's just creating yet another flavor of Typescript... and why straight out adopt that type syntax? Because it will please Typescript developers and Microsoft?
All for what? being able to run that flavor of typescript without having to compile typescript files into Javascript? It would change nothing to the already complex build pipelines JS developers are already mandated to use for production.
I agree with the parent, this is a bad proposal.
What Typescript should do as an alternative is better support for JSDoc type analysis. I don't use typescript language, however I do use typescript compiler.
https://www.typescriptlang.org/docs/handbook/jsdoc-supported...
Does it defeat the purpose of typescript? No, typescript is both a language AND a JavaScript static type analyzer.
The developers of TypeScript. TypeScript aims to avoid adding anything to the runtime as a result of the type system[1].
> It would change nothing to the already complex build pipelines JS developers are already mandated to use for production.
You're right, it wouldn't change anything when you're building for production if you're doing things right. It would mean that you don't have to repeatedly compile your code while you're developing it though.
> What Typescript should do as an alternative is better support for JSDoc type analysis.
If you read the proposal you'll see they explain why expanding JSDoc is not ideal. Personally, I wrote a lot of JSDoc back before TypeScript and now I don't want to touch the stuff. TS is much more ergonomic and expressive.
[1]: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Desi...
At risk of running afoul of HN guidelines: did you actually read the post?
The proposal does not add type checking to JavaScript. It adds type syntax. There is a huge, huge difference.
Their proposal is to implement a comment-like type syntax. These types would be totally ignored at runtime.
This isn't "run TypeScript in the browser"; this is "add syntactic sugar to vanilla JavaScript to get the development benefits of types without a build step."
Yes, JavaScript engines would have to implement a parser for this syntax. Yes, this raises the barrier to building a new JavaScript engine.
Does that mean JavaScript should add no new syntax ever again? No, of course not. So the question becomes one of cost-benefit analysis. And I think the TS team has submitted an extremely compelling argument for the benefits.
Your comment acknowledges the existing benefits of types-in-comments; think of this proposal as a significantly nicer way to write those.
Yes? Yes. Maybe?
At least not in cases where the language can already do things adequately, and the change is just a cosmetic improvement. Annotating comments already works, changing that just to have a syntax that looks like type hinting but isn't just makes the language worse in my opinion. I'd rather they just bite the bullet and add optional type hinting, and make the syntax do what it appears to. Otherwise, the necessary complexity of typing Javascript should be kept entirely out of the language itself - including special syntax to make things easier. Deal with Typescript and its peculiarities and the build step, if that's what you want to do, and annotate types in the existing comment syntax, but Javascript is an untyped language and should be remain absolutely, even aggressively agnostic about such things.
My complaint is about adding type parsing in the browser. When I say "run typescript on the browser", I mean running code written in typescript syntax.
Please read my comment again with that in mind.
"Large swathes" is really overstating it. The TS philosophy has been to avoid runtime behaviour for quite a few years now, and while there are a few features that made it in back when they weren't so strict about that yet, they wouldn't have added them today and have worked to add alternatives that do not modify runtime behaviour (like literal string union types). So it goes as much "halfway" as all TS development has gone for the past few years.
I mean this is a great idea, removing one more of the many many complexities in simply getting a nodejs package to browser and debugging (getting accurate source info and avoiding transpile errors are a PITA). JavaScript is an interpreted language yet 90% of the time it’s not even run interpreted. But “a proposal for Type Syntax in JavaScript” when TypeScript and JSDoc exist is just confusing and redundant.
It's Microsoft imposing their technology on the ECMA committee.
Ironically the same Microsoft that rejected ES4. We wouldn't be needing Typescript if ES4 was adopted 15 years ago...
edit: While this proposal doesn't have runtime typechecks, it's just one step toward adding runtime typechecks it isn't a stretch to think that if this passes, runtime typechecks might eventually be added to the language. ActionScript 3/JScript.net/ES4 had them, so it's perfectly possible for Javascript "with types" to add them as well.
I wasn't there for ES4; however, the type semantics of ES4 is a drastically differ from what's being proposed here. There is some information on the FAQ about why runtime types are a non-starter. (https://github.com/giltayar/proposal-types-as-comments/#why-...)
This comment probably won't count for much - actions speak louder than words. Hopefully we can demonstrate that we're being genuine here.
1. While care was obviously taken to be type system agnostic, and while TypeScript is obviously the current incumbent, I think there could be more of a sign of collaboration with Flow, Closure and Hegel.
1a. They’re notably mentioned but conspicuously no one from those projects is listed as authors/champions. This suggests to me that they weren’t (substantially) consulted in drafting the proposal, which implicitly weights the proposal’s details in TypeScript’s favor if only by inertia.
1b. There’s surprisingly little “give” in terms of the few minor differences between Flow and TypeScript. I’ll grant the potential reservation of `opaque type`, but strongly suspect that’s because opaque types are already under consideration as a TS feature.
2. Omission of certain runtime-affecting constructs is certainly pragmatic, and not omitting them almost certainly a deal breaker for the proposal. But, it’s also quite likely to fragment TypeScript, effectively deprecating those parts of the language (which I’m sure the TS team would prefer to do explicitly, but well, that’s a much heavier lift).
3. This limited subset of TS syntax almost certainly is a real superset of JS, but there are some parsing disambiguation complexities to consider, particularly for type parameters on functions as well as (if ultimately included) function overloads and bare property modifiers. This also affects runtime performance, particularly at load time which is critical.
4. Omitting JSX makes sense in the current state of the world, but does it make sense for the goals of this proposal?
4a. JSX usage outside of TS has an almost totally overlapping motivating problem: the need for a build step. It doesn’t fit the proposal now, because JSX (usually) has runtime semantics, but they’re unspecified without build time configuration.
4b. Of all things that will fracture TS, this one is irreconcilable. I’m honestly surprised it’s even being considered by anyone on the TS team.
4 (conclusion). Given 4a/4b, JSX almost certainly should be a separate proposal, but I think it should seriously be considered as a potential prerequisite.
5. The goal of rapidly evolving TS and conservatively evolving TC39 is a balance that probably can be struck, mainly because the TS team has been incredibly good at keeping their syntax and semantics aligned with standards. But baking type comments into the language with a variety of new syntax blocks that syntax from being used for other proposals. For type-only syntax that’s obviously not a huge deal, but I’m imagining a fair bit of push back on reserving, say, the colon character in function positional arguments.
Probably more I haven’t thought of. And I want to reiterate I think this is a great idea in the abstract. I want to see it succeed. If the champions or any of the TS/Flow/Closure/Hegel teams, or anyone else here thinks any (or all) of these concerns should find their way into issues on the proposal repo, please feel free to copypasta or ask me to do same.
It would actually be a net negative for JS, as it would allow the syntax to be shipped on sites, and then because it isn't actually checked at runtime you will inevitably end up with sites if the engines ever do start performing type checks, and so will directly prevent them from adding it later.
So as I understand things:
* This does not actually add type checking
* It does not support the full typescript syntax, so you don't get to skip a compile stage
* This prevents JS engines actually adding type checking later, due to breaking existing content
I am unsure why you believe performing the checks is untenable if TS already does them? The runtime checks should be relatively cheap and in perf critical code if it turned out type checks were too expensive there are a bunch of optimizations engines can do, or the impacted functions could drop the annotations.
Adding a significant parsing surface, with the related page load perf impact, with the potential (im going to be generous) to burn the syntax, this seems like nothing but downside.
TS runs the checks at compile time and compiles to JavaScript without annotations. There is no runtime cost.
> related page load perf impact
Type annotations would likely still be stripped by minifiers, just like comments. No change.
> burn the syntax
As a dev that regularly uses TypeScript, being able to use debug builds with annotations and copy paste TypeScript into the console would save a lot of time. This would be part of larger trend of adding type annotations to dynamic languages. Python, Ruby, and other dynamic languages have blazed the trail here. There are ways to add enforcement in the future if needed, just look at 'use strict';
If there were performance costs this can be mitigated very easily - to be able to do compile time checks means TS is designed largely around early binding, at least in the default case. A JS engine can do this trivially.
> > related page load perf impact > Type annotations would likely still be stripped by minifiers, just like comments. No change.
You're kidding right? You're proposing permanently changing the language, in a way that burns the type syntax for a feature that you're now saying will be stripped before a JS engine ever sees it?
> As a dev that regularly uses TypeScript, being able to use debug builds with annotations and copy paste TypeScript into the console would save a lot of time.
That sounds like a feature for your console, not the language
> This would be part of larger trend of adding type annotations to dynamic languages. Python, Ruby, and other dynamic languages have blazed the trail here.
Which enforced the types. Understand I am not opposed to the type annotations, I am opposed to this because it does not enforce those types. That means that broken content will exist, and thus burn the syntax.
> There are ways to add enforcement in the future if needed, just look at 'use strict';
Which will never happen again. As the person who implemented strict mode in JSC I can tell you that the cost of a mode switch is massive, in spec and implementation complexity. Adding another mode switch is simply not going to happen. The only reason I was ever ok with adding strict mode to javascript was the removal of the this conversion. No other part of strict mode would have warranted the cost.
I'm not one to argue, computers are fast. However, this would be a huge paradigm shift for the JavaScript ecosystem, where compile-to-JavaScript-tools like TypeScript are dominant. These tools have explicit goals to do type checking at compile time only and avoid generating anything at runtime. Runtime checking is redundant in this paradigm.
Now if you're arguing that the JS engines like V8 should be able to use type information for performance gains, I understand that wish. WebAssembly seems to be taking over the performance angle these days though, as it was designed from the start for that purpose, unlike JavaScript.
> You're kidding right? .. will be stripped before a JS engine ever sees it?
Yes. We're talking JavaScript here - billions of lines of which are compiled every year to ES5 ;-; with polyfills. Throwing away hundreds of useful features of ES2016+. This is par for the course, part of the JavaScript paradigm which this proposal understands.
> sounds like a feature for your console
That is fair, though it seems unlikely Chrome would adopt such a feature for their console without motivation. Perhaps.
> Which enforced the types
Python does not enforce types at runtime? You might be referring to something I'm not familiar with. Fired up Python 3.9. This works fine even though I'm passing strings for int.
> the cost of a mode switch is massiveBut earlier you said a JS engine can do this trivially? I don't understand how this is now difficult. Ultimately, if the types are enforced, you may as well go the full monty and support TypeScript in the browser, with Deno leading the way. Stop beating the JavaScript horse and all. That's the dream. This proposal is a compromise without a doubt, with the understanding that TypeScript in the browser is politically untenable at this point.
I really don't understand.
It wouldn't have to support any smaller granularity, and it wouldn't need to change parsing at all.
Google's V8 team (the team that owns Google Chrome's JS engine implementation) floated a proposal back in 2015 to implement a new JS mode that they called "Strong Mode."
https://docs.google.com/document/d/1Qk0qC4s_XNCLemj42FqfsRLp...
The idea was that you'd opt-in with a pragma like "use strict", but this time you'd "use strong". Strong mode would include a bunch of restrictions on how you'd write your JS. For example:
- class prototypes would be frozen; it would be forbidden to add properties at runtime, or to `delete` properties from a class
- The "new" keyword would automatically Object.seal() the object
- Arrays are non-sparse
Here's Google's 2016 announcement canceling the "strong mode" experiment. https://groups.google.com/g/strengthen-js/c/ojj3TDxbHpQ
> 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.
There were other problems, too, some of which are substantially mitigated now in 2022. Maybe it's worth a try now!
…but if you're hoping to hold up type comments until "strong mode" works, well, I just don't think it's gonna work.
And so, in practice, for the next five to ten years, we're either getting something pretty much like Microsoft's "type comments" proposal, or nothing at all.
I personally don’t want runtime type checking anyway[0]. Apart from my concerns[1], most of which are fairly navel gazey, I support the type comments proposal almost exactly as is.
My hope is that if others are successful asking for runtime type checking, they’re also asking for the corresponding performance problems to be addressed in tandem.
0: We already have runtime type checking: type guards. They have the advantage of being optional and explicit, which addresses performance concerns better than anything else I can think of.
1: https://news.ycombinator.com/item?id=30621120
My general opinion is the complexity of JavaScript is increasing quickly.
Should JavaScript eventually end up like, say, TypeScript? I'm not sure.
I would be for it if it was possible to keep TypeScript metadata somehow so I wouldn't need to create schema with Zod but with TypeScript. There was babel plugin like that for Flow and it was nice PoC and I guess similar could be done via some annotation with TSC.