TC39 Proposal: Type Annotations
github.com
github.com
Maybe it means that I don’t have to preprocess / compile TypeScript before running it. This is a genuine win for me. The TypeScript compiler can continue doing what it does best—type checking—and then I can just run the code. Running the TypeScript compiler from a cold start takes a surprisingly long amount of time.
Currently, I have to figure out how to get a build system that compiles TypeScript once for bundling to the browser and once for running in Node, and the user experience around setting this up is just incredibly bad. It sucks. I make some change to how I build for browser and it turns out to be incompatible with whatever system I am using for Node. This solves part of that problem, and reduces friction. Type annotations can be just part of the JS and stripped out by minification.
For backend node, you simply edit a couple of lines in the package.json to use ts-node during dev, and run tsc for shipping builds (a bit more performant than ts-node).
For frontend usually you literally don't configure anything, Next.JS, CRA, or whatever already comes with typescript preconfigured if you select it. And if you do everything manually, considering you still need to setup babel, webpack etc, it makes almost no difference.
It seems quite extreme modifying javascript for this considering you still would want to remove types in order to reduce bundle size, and you would still need the actual compiler because you have things such as enums, annotations and more that JS doesn't support either.
This post feels like a trivialization of how complicated everything is, how complexly interlinked build systems are.
It also misses one of the biggest harms. It doesn't consider what a pain in the ass it is when the source/libraries you are consuming have already been downcompiled into lesser JS via someone elses perhaps-poorly configured build pipeline. I'd guess that >80% of TypeScript modules don't export ESM right now. TypeScript 4.7 is about two weeks old & it's the first time TypeScript and Node's ESM play well[1]. Because it all involves complex transpilation. How many modules do you think will get updated, ever?
You know what would be great? If we could just write code. If we didn't have to worry about build pipelines. If my toolchain could make what it would of other code, be it JS or JS+TypeScript Type Annotations or JS+Flow Type Annotations.
> "For frontend usually you literally don't configure anything, Next.JS, CRA, or whatever" "For backend node, you simply edit a couple of lines in the package.json"
The amount of dissympathy for the real complexity here, for how hard a couple specific projects have worked to make things "just go" is staggering. The amount of ink spread to support, the amount of stack overflow questions struggling through, is probably enough to reprint the Apollo Missions guidance software a couple times over.
This is hard stuff. It's complex & interlinked. There are not singular solutions; there's many many interlinked & complected tools & systems & options.
Easing the path back towards- it will work. Towards just being able to ship code, without necessarily needing to typecheck it, transpile it, downcompile it: it helps a huge range of people who are really really in need of help. Who don't have teams, companies, support. Who just want to start to learn, want to start to get going. This change may or may not (I'd argue more that it may but...) have huge impact on your life as a highly-late industrial supercorp developer, but it has huge impacts on the ecosystem, it's approachability, it's friendliness. Writing all that off, just pretending we have some magic wands we can wave & these dilemnas, these pitfalls, are not really here: woe be un to us if we are not willing to assess the real cost of this all. I can't see your post as taking for real the costs.
JS used to be extremely low cost & light weight to play with, to get started with. It used to be a joy. It still is, but the barrier to entry is much higher, using modules has never been the same dream as slapping some <script src="http://jquery.com/jquery.js"></script>'s down on the page (not a real link) and having it just work. This goal is fulfillent to a noble & excellent intent to once again spark joy.
[1] https://devblogs.microsoft.com/typescript/announcing-typescr...
Most people write code using esm for the past few years. If anything the problem is that shared libraries are only exporting esm so tools like jest that still require commonjs don’t work.
Just use Tsdx or other tooling to automatically expose the different bundle types.
Even still, if JS developers took the time to understand the different module types we would be in a much better place on the shared packages front
But what do they target? TypeScript projects targetting only es2015 or only cjs are all too numerous.
Much of nobility of this Type Annotations work is we could (potentially) stop transpiling. The source could be the source.
> Just use Tsdx
Just use ____ is the center square of the JS bingo game. It's a terrible answer, but it's almost always the answer, and the answer always changes.
That there's an ever rotating constellation of "just use" answers to newcomers questions, all of which are semi-required "zero configuration" "just works" new tools to fix the previous pile of cobbled together stuff: painfully Python-esque.
I agreed with every single thing you wrote until that last line. In what universe is the ever-changing mess that is the JavaScript ecosystem even remotely comparable to the Python ecosystem?
My understanding is recently Python docs have started to encorporate a little more guidance on handling dependencies in virtualenvs, and some specific suggestions & write up about tools. Which is great.
I think your right that JS probably has a lot more build/compiling/lifting machinery, & is much more confusing. To be fair, it also has a much harder job (since the build-target is only sometimes the local machine).
This episode isn't 100% current, but still relevant and discusses this issue: https://changelog.com/jsparty/137
Over a decade, before all these tooling existed.
> This post feels like a trivialization of how complicated everything is, how complexly interlinked build systems are.
I know build systems can get very complicated, in fact it's part of my point. Which is that considering you already need to set up a build pipeline, adding typescript support is quite simple.
> You know what would be great? If we could just write code. If we didn't have to worry about build pipelines.
But that will not be the case. People are not FTPing their dev folders into prod anymore. Even with this change, you will still need a build pipeline, as everybody already does regardless if they use TS or not.
> JS used to be extremely low cost & light weight to play with, to get started with. It used to be a joy. It still is, but the barrier to entry is much higher, using modules has never been the same dream as slapping some <script src="http://jquery.com/jquery.js"></script>'s down on the page (not a real link) and having it just work. This goal is fulfillent to a noble & excellent intent to once again spark joy.
I disagree with this. That's probably nostalgia talking. Slapping some script URL and editing with Notepad++, having absolutely no IntelliSense, no errors/squiggly lines and having to F5 a browser after every change, trying to hit the code path in question and check the browser console for errors was awful.
Nowadays the editor will tell you what's wrong as you type it, the browser will automatically refresh the code while maintaining state and so on.
I think you conflate the development environment with the hypermedium. You stick lo-fi tools with shame, but you're not actually talking to the language & it's lightweight versaility & hackability. You're not talking to the editability, the malleability, & simplicity of the medium as it was, and which, if we can do just a little bit of healing, can be again.
> Even with this change, you will still need a build pipeline
Will we? Why? I tend to wager a decent static webserver (especially one that has decent cimpression built in) will be a very fine deploy target for many again, soon. ESM, early-hints, http3... it could happen. Yeah we probably should strip comments & these type annotations, but need to? Meh. I think we fret too much about the small stuff & havent spent nearly enough time conisdering incremental loading architectures & better use of service workers. The endless pish for optimizing what we have has been a race of folly ignoring the real peaks around us daring us to be summited.
JS can & should be less build intensive. Non-build module-using js was the high fantasy we were driving for a decade ago, when the idea of modules was new, & it's been slow, but that objective was there for really good & importamt reasons. A js which is naturally accessible, which is evident & real, is good for humanity & how the web reconnects with itself as a hypermedium, as more than just another shitty developer app-dev toolbox for nerds like us. We can be better. We can make the source real again.
Even with http3 and so on, serving node_modules which almost always is 100k+ files would be awful. And of course, yes, you don't need npm. But I don't see people going back to the jquery days of having a single o no dependencies.
I guess the point stands for new people learning web development who are only playing on localhost and don't care yet about having something good enough for prod. But I don't think people who are at that stage should worry about typescript. If they did and didn't want a build pipeline, they would just manually run tsc. Is adding a new feature to JS just so that beginners who want to use TS don't need to run tsc worth it? IMO no.
These hackernews developers always act like it’s the most blissful thing
“If only we could just write JS without running a special transpile command”
That’s actually a much worse developer experience. If you’re using any modern frontend technologies, you’ll want to have a dev server running.
Using hot module replacement at a bare minimum (where your browser updates the screen without doing a page refresh, instantaneously)
Is a much better experience, so you should already be running a dev server anyway if you’re being productive is the point…
It completely ignores what it takes to get started, or how alive & malleable the web is.
The domination of concerns by deeply deeply industrialized ways of thinking holds back the joy of the hypermedium we work. And it truncates human potential. Making code & coding accessible is a virtue. One that could cost us nothing.
> For frontend usually you literally don't configure anything, Next.JS, CRA, or whatever already comes with typescript preconfigured if you select it.
My experience is that this stuff is always on the verge of breaking when you integrate it with some new dependency, when you have needs that are slightly different from the mainstream use-cases that the developers envisioned, or when you start going through and updating your packages.
I’ve been using JavaScript since the dark ages and the only way we can survive is by periodically cutting down some of the built-up complexity. We don’t need to cut it down for everyone, and not all at once, and no change is without its drawbacks. I’ve used create-react-app, I worked at a company that used machine learning in the JS build pipeline to do code splitting, I’ve used vanilla JS, and I’ve written some pretty damn cursed build systems for stuff like JS13K or 1K coding competitions. TypeScript sticks out as a rough spot in most build systems I’ve used, and the reason I still use it (most of the time—not always) is because the typechecking and IDE experience are just so damn good that it justifies the cost.
> It seems quite extreme modifying javascript for this considering you still would want to remove types in order to reduce bundle size, and you would still need the actual compiler because you have things such as enums, annotations and more that JS doesn't support either.
Not every change is applicable to all uses cases for everyone. That’s ok. If you decide to write TypeScript without enums you usually find that you don’t lose that much—it’s easy enough to do something like:
type LogLevel = "error" | "warning" | "info";
Obviously this is not a one-size-fits-all trick, but I find myself using TypeScript enums less and less these days.There are also some dirtier TS tricks you can which let you create something kind of like Haskell’s newtype—pure type system stuff.
TypeScript used to have more sugar, and that sugar had been removed and merged with the equivalent ES functionalities. Dig through old TS versions and you’ll find obsolete syntaxes or semantics that have been removed.
Just to pick an example, TS had class before JS. IMO the ideal scenario here is that TS is just type annotations on top of JS, and any features you use which aren’t universally available, you polyfill/transpile as a separate step.
This means TS is just types, and your transpired/polyfills are just transpilers/polyfills. To achieve that, TS classes are modified to match JS classes.
My sense is that TS will not add new stuff not in JS any more. It’s simply not a direction TS is going. I also get the sense that enums are a mistake in TS’s design.
TS in some sense is a reaction to the lessons learned from its predecessors, like CoffeeScript.
TS goal IMO should be to offer the best developer experience, while maintaining interoperability with the JS ecosystem. Not just limiting themselves to types.
Why do you think enums are a mistake? Enums allow you to have autogenerated mappings from symbols to integers. You can't do that with types as you showed in your example.
That’s why enum should be avoided in TS or added to JS.
I can understand why people want TS to be a “better” language, but these days, ES is pretty good and a major part of TS’s success is that it follows JS semantics almost everywhere.
Not languages that can interoperate with JS the way TS does (except for flow and similar type checkers).
TS success is that it's a superset of JS (unlike say CoffeScript). So you can throw some JS and it will be valid TS. The point of being a superset is that you can add new stuff. Types, enums, annotations.
So the only argument why enums are bad except for that it's not in JS? Why does it matter, just because a JS developer has to learn more things if they switch to TS? The whole argument hinges on the premise that TS should not add anything that JS doesn't have except for types, but why is that?
Really the only reason to do pre-processing is if you want to do some optimization beyond what the browser can do, or if you want to write a syntax which is not supported by your target runtimes. And for many developers (including most library authors) this is not the case.
It's really hard to guarantee a world where my complete dependency tree meets my target runtime requirements (eg: I might also not be using nodejs-style require, but my dependencies could be), so pre-processing seems like something that will be with us for some time.
ESM imports are the standard, unlike Node’s require. And you can now write ESM code that’ll run flawlessly on the backend and the front end without any transpiration. IMO that’s huge. Type annotations remove yet another blocker.
As pointed out by this proposal the JSDoc annotations are—to put it mildly—a bit cumbersome. The more complicated types are close to impossible to figure out how to write, if they are possible to write at all. And on Q&A forums I constantly have to translate between the two syntaxes in my head, since most of the audience will probably not understand the JSDoc syntax.
Having a unified type annotation syntax which the runtime ignores will definitely make my life easier.
// TypeScript
add<number>(4, 5)
new Point<bigint>(4n, 5n)
> The above syntax is already valid JavaScript that users may rely on, so we cannot use this syntax as-is. We expect some form of new syntax that could be used to resolve this ambiguity. No specific solution is proposed at this point of time, but one example option is to use a syntactic prefix such as : // Types Annotations - example syntax solution
add::<number>(4, 5)
new Point::<bigint>(4n, 5n)
> These type arguments (::<type>) would be ignored by the JavaScript runtime. It would be reasonable for this non-ambiguous syntax to be adopted in TypeScript as well.----
Hmm I didn't know this, so I tried it myself in Chrome's console... sure enough it works...
new DOMPoint<Number>(4,5)
Given that the above works in the browser, what exactly is it doing? I've never seen angle brackets used that way in vanilla JS codeComma operator makes (4,5) = 5
https://astexplorer.net/#/gist/b0dff7bdaf1d8f9024fe18fda70a9...
(new DOMPoint < Number) > (4, 5)
(new DOMPoint < Number) evaluates to true and it becomes (true) > (4, 5). Because (foo, bar, baz) syntax always evaluates the last item, we can finally simplify it into (true > 5), which surely enough in Javascript evaluates to false.> The above syntax is already valid JavaScript that users may rely on, so we cannot use this syntax as-is.
What users would be using said syntax? Why would one compare a function to a type? If we're making a backwards incompatible change, just say that `func < type` is a syntax error unless immediately followed by the rest of a call. IMO, in any spec committee, if a naysayer says that "someone may be using that syntax", they should be required to prove it. Prove that someone is comparing a function to be less than a type, and why they'd do such a thing.
Honestly, I don't see how this can be done in a backwards compatible way short of type annotations in comments. Just rip the bandaid off and have WHATWG say that TypeScript is a valid runtime and allow `<script src="..." type="typescript">`. Deno manages to have a TypeScript runtime just fine.
Aggressively minified and optimized JS code results in all sorts of weird things.
Unless one can find some minifier producing said example, it’s a bad argument.
If you want to uphold a commitment to backwards compatibility, you simply cannot extend your language in a way that might possibly change the behavior of valid-but-nonsensical code in the wild.
const number = 5;
function fn(number: number): number
That means that we can’t always know whether we mean the type or the constant when we type: a<number>(b)Apparently C++ parsing is undecidable, so building an AST requires arbitrary template instantiation (and C++ templates are turing complete).
The turbofish is a compromise that allows the parser to stay simple. I know there were efforts to remove it, but it appears to be here to stay.
https://github.com/rust-lang/rust/blob/master/src/test/ui/pa...
Possibly the people behind JSFuck and derivatives. :)
Oh, buckle up!
new DOMPoint<Number>(4,5)
Let's first clean things up a bit: DOMPoint an Number are just identifiers. So, let's replace those with a and b: new a<b>(4,5)
Let's also add some spacing around these tokens to distinguish them better: new a < b > (4, 5)
Yep, those < and > are comparison operators.And let's also add some parentheses to make clear the order of operations in these comparisons. The above expression is equivalent to:
(new a < b) > (4, 5)
Now, let's remember that a is DOMPoint, so `new a` is just instantiating a new DOMPoint object. Yep, the parentheses at the end of the `new Something` calls are optional if no parameters are passed. > new DOMPoint
DOMPoint { x: 0, y: 0, z: 0, w: 1 }
(That's the result of trying that out on a JS console. The initial > on the first line is the REPL prompt, not part of the JS syntax. And the second line is what the REPL prints.)So the < operator is comparing a DOMPoint object to b, which is Number, which is just a constructor function. IIRC, what JS does is these kind of situations is to convert both operands to strings and then compare those.
> (new DOMPoint).toString()
"[object DOMPoint]"
> Number.toString()
"function Number() {
[native code]
}"
So the first < comparison is going to compare these two strings, and since '[' is less than 'f' (of course... ASCII), the < result will be `true`. The whole expression can then be reduced to: true > (4, 5)
The right-hand side of this > operation, `(4, 5)`, is curious. The parentheses are just normal parentheses for grouping expressions, but what's inside of them are two expression joined together by the comma operator[1]! Basically, both expressions, 4 and 5, are evaluated, one after the other, and the result of the whole is the result of the last one: > 4, 5
5
So, we're almost there! The whole thing can now be reduced to: true > 5
Since one of the operands is a number, JS tries to convert the other one to a number too. `true` converted to a number yields 1, which is not bigger than 5 — finally, something that makes sense!So now we know why the whole thing that looks like TypeScript but isn't, is valid JavaScript and evaluates to false :)
> new DOMPoint<Number>(4,5)
false
1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... true > 5
> Since one of the operands is a number, JS tries to convert the other one to a number too. `false` converted to a number yields 0, which is not bigger than 5 — finally, something that makes sense!You meant that `true`, not `false` which doesn't appear in this partially evaluated version, is numified, right?
When using a bundler, it will be trivial to remove the annotations in the build process.
Using a TypeScript transpiler in that process is also trivial you might say. But static typing syntax and tooling as part of the language itself is the way to go imo.
But if the typing syntax is essentially just comments in very specific places... what advantage does it bring? Sure one can use tools to interpret those comments and check types... but at that point, isn't just using typescript tooling much superior (interface declaration, type declarations, etc. not just a type between : and =)?
I will confess that I am guilty of having used JSDoc comments for quick and dirty .js scripts that I didn't want to grab the tsc compiler for, but still wanted vscode to check my types. But even being one of the likely users of this proposal, I feel that it's needlessly bloating the language.
The advantage would be, that static typing is part of the language. Don't you find it odd to use another language just for a missing language feature? For me it feels somewhat hacky and '// temp. solution!!! fix soon!'-worthy.
But i'm thinking out loud now.
No. Why do you?
For a language to not try and have all the features it possibly can is a feature.
I mean, i like TypeScript a lot. I think i do find it odd, because i'm used to using languages, that are constructed with a certain feature set. Obviously Java/ECMA Script evolved a lot more chaotic than most other languages.
Transpiling a superset of a language to its subset introduces indirection, which makes it feel hacky imo.
I feel like, if there is another language feature we want to add in the future, how should that be injected? In form of a superset of TypeScript?
I would be cool with TypeScript as the target language, though.
It means the supplemental information needed to run either static or dynamic type-checking is there & so that either browsers or toolchains can use it.
And it means that the code would just run on existing systems. For production we'd probably want to strip out comments, but for production we already often do strip out comments (which I wish could be "undone" on most sites by users wanting to know! View source!!).
Let's turn your question around: what advantage does existing typescript language have, over a backwards-compatible & type-carrying enhancement to JS?
The format isn't specified, it's just a comment. Browsers can't take advantage of it. Toolchains already do cross-compiling when they're bundling anyway, so it's not required on that front.
>what advantage does existing typescript language have, over a backwards-compatible & type-carrying enhancement to JS?
Typescript is on a much faster release schedule than the standards. Just think of how slowly its (amazing) type system would've evolved if designed by committee.
I'd be all for a type system in javascript a couple of years ago. But seeing how fast typescript evolved when it's not limited by a committee, I think that keeping that separate of the main language is completely acceptable.
The authors intend to support a variety of type systems, such as TypeScript & Flow. That TypeScript would need to define it's own grammar doesn't seem harmful, & would surely be standardized quickly, exterior to this more general spec.
Latter you say: "Typescript is on a much faster release schedule than the standards." Well, since the format isn't specified, TypeScript is free to release at their leisure. Not bundling orthogonal concerns together, providing low-level extensible capabilities is a win.
> Browsers can't take advantage of it.
Why not? They could.
> Toolchains already do cross-compiling when they're bundling anyway, so it's not required on that front.
Ok, but you're ignoring the goal of this proposal: "The aim of this proposal is to enable developers to run programs written in TypeScript, Flow, and other static typing supersets of JavaScript without any need for transpilation"
They syntax isn't fully specified (it does some basic syntax checking on the top level, but doesn't check anything inside brackets). Asking browsers to support every variation of type declaration syntax that will come out is a lot (even if that turns out to be just typescript and flow). Why bloat the language and implementations?
Unless you propose an unified syntax for types... in which case it will hurt innovation as we won't ever be able to make backwards breaking changes, as people will rely on all sorts of quirky behavior.
>Ok, but you're ignoring the goal of this proposal: "The aim of this proposal is to enable developers to run programs written in TypeScript, Flow, and other static typing supersets of JavaScript without any need for transpilation"
Right, but why is this desirable? What does this bring to the table other than some convenience in exchange for adding more bloat to the language & implementations?
If you want browsers to also type-check, then you're also adding more complexity to implementations. In exchange of a small bit of convenience?
If you want the type-check to be used for optimizations, while a noble goal, would require some massive reengineering of current javascript engines. It's already possible to get optimizations that come from static typing by compiling things to webassembly instead (so they can use existing pipelines, like llvm. Assemblyscript comes to mind, it tries to be similar to typescript but with mandatory types).
A lot of optimizations might not even be possible to do even with type annotations, unless they're a lot more strict than typescript's. See the following examples:
* https://www.typescriptlang.org/play?#code/G4QwTgBAZg9jBcEDOA...
* https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8...
* https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8...
JS engines already optimize number-heavy code when they can identify that variables are always going to be numbers.
A pragma at the top, "use typescript" that the browser could handle would bridge 98% of the rest of value while not overcommitting the language to a specific cause.
This is all free cheap easy wins. Easy.
yes maybe with a 'use typestrict' directive or something.
If you are going to transpile/bundle your assets, you're probably using webasm at some point...or not!?
And nobody forces you to have typed minified JS in your bundles?
My feelings are still the same in that I don't support the proposal.
Theoretically, there would be no more need for compilation tools after this change is implemented.
In practice, lambdas need to be bundled, frontends still need to be bundled and running typescript in node efficiently nowadays should be as easy as `node -r @swc-node/register path/to/file.ts`
So this will actually not ease the JavaScript tooling nightmare.
That said, I'm not convinced this would actually remove one of them:
- It would mean shipping more code which is a no-no
- It probably won't ever cover the whole of typescript's features, so many people will continue to use that, and will still have to transpile
I'm sure this will help... somebody, but it's going to be a very narrow set of workflows that benefit
Obviously it’s not something you’d do in a normal production environment. It’s nice to be able to run code without any compilation steps if you’re working on something small (e.g. some demo on my personal website) or something in a development environment.
I’ve done this. Served up JS with “import” statements everywhere. The devserver just served JS straight from the filesystem without modification. When I change the JS, the browser just needs to reload—there’s no build process, no waiting. The production environment ran it all through Closure. Closure also ran in the dev environment, but it ran asynchronously, in the background, telling you what the errors are.
No source maps to deal with. No delays. The browser gets exactly what I write.
Prototypes / dev are important.
Production bundling can then be as simple as running `deno bundle index.js` or similar.
If you don't want to take the performance hit of type checks, you can still check and then remove type annotations during bundling. Having this would just mean that we will never ever ever get actual static typing in javascript, so it's actually worse than doing nothing.
Since that backtrack, the Internet has always been about displaying something at all times.
Adding types to JavaScript and hard failing when they’re incorrect is not a JavaScript anyone wants to publish. We’d rather have the forgiving but messy JavaScript than the one that stops a webpage from working when it gets a different data shape from a JSON endpoint due to runtime checks.
Nobody actually wants runtime checks on the web unless you’ve a way to opt in to them. And guess what? You could. There’s nothing stopping you from writing a compiler that adds runtime checks to your code. In fact, that’s pretty much what code generators do for typescript when they create validation functions to make writing or working with APIs a bit easier.
Type annotations in a language that don't actually annotate types for an interpreter of that language literally do nothing. Might as well just use the existing comment formats to do the same thing, and be more syntactically explicit:
function foo(bar /*TS:int*/, baz /*TS:int*/)What we’re talking about, though, is the reason the ES6 arrow syntax exists. And it’s not just because of “this” binding. It’s because JS developers are lazy. What you’re suggesting is extra characters. And clutter.
These days if you pick a JS project or dependency and try to ignore the ones written in TypeScript, you’ll be left with very, very few viable alternatives. Do JS-only projects exist? Yes. Plenty. But the number of modern JS-only projects are far outnumbered by the number of TS projects, and the discrepancy is only going to grow over time.
What’s sealed the deal was TypeScript adhering as much as possible to JS standards and not inventing new runtime conventions and weird syntax. When they made that pivot, to a JS + types approach, that was genius. It helped everyone remind themselves that TS was JS with types, and not something different like Dart.
Taking this another direction, the power of TypeScript has been its ability to evolve as a language without breaking JS compatibility. If you bake types into JS, you risk breaking compatibility with some improvements to the type system. By keeping types out of the runtime, only the developer toolchain needs to worry what version of Typescript might be required to build a particular package. We don’t have to invent a way of marking some scripts as v3 and others as v4 TS.
Until now, JS has been largely future-compatible while TS has rapidly evolved and occasionally broken existing code. It’s of course possible to add types to JS, but are we convinced we have a perfect type system to do so now, or could it not wait and evolve a bit first?
We can always make a backwards-compatible language change later, such as a syntax to turn on or turn off runtime checks.
By allowing but ignoring types, you get the best of both worlds - optional type checking and runtime compatibility - without further compilation.
Frankly I think of this feature as a Node.JS feature and a reduce-duplication feature. You can store and run the same TS syntax in a file with a .JS extension.
Today, I often find TypeScript samples that I copy into JS projects and then have to painfully remove the TypeScript bits to get it to run. This fixes that. Your IDE can benefit from reading the types and tell you about errors - that’s where you can fix them anyway.
If you want <script lang="TypeScript" … /> to work, with compile type checks and everything, that’s a different feature?
Why should javascript add syntax just to make users of another language more comfortable?
>Today, I often find TypeScript samples that I copy into JS projects and then have to painfully remove the TypeScript bits to get it to run. This fixes that.
The purpose of typescript is to be compiled into javascript, it isn't meant to be run in a browser. If you're going to use it, use it properly, otherwise, "picking out the typescript bits" makes about as much sense as "picking out the C#" parts of some .NET code to run it in a C compiler.
ECMAScript 4 was canceled for a whole host of reasons. Trying to blame browser vendors is just bonkers. The standard made too many changes all at once and existing work on implementations had progressed too far.
We can’t change the past. Unfortunately we are reinventing a lot of what was done in that early work, but now with some strange syntax because of compatibility with dead features or 3rd party libraries that picked up the slack. At least we finally have a standard for importing packages…again.
JS engines could do the same!
Let's start with the first steps: getting the information.
or only warn.
i don't think anyone would consider turning it on by default everywhere. this seems like an extreme non-issue.
There's nothing I see in this proposal to prevent a user-agent from running a static analysis on JavaScript input into the console or DOM editor before trying to interpret it. If what you're saying you want is for the typechecking to be done by the user-agent for every piece of downloaded JavaScript... Why? I mean, a user-agent could be constructed to do that, but it'd be inefficient over just trusting the vended code (which, in a sense, we should probably just default to doing, because nothing stops the developer from type-asserting or omitting types so in the grand scheme of things, the code is exactly as provably sound if we typecheck it before running as if we don't).
What would "actual static typing in JavaScript" look like that this proposal isn't?
I want the browser to reject feeding a string into a number parameter of a function, at which point it does this isn't important to me as much as that it should be more than just a comment that is ignored completely.
There would absolutely have to be an escape hatch, or configuring one's browser in this way would make most of the web fail to work (and unfortunately, the golden rule for features in browsers is "if it breaks most existing sites, you can't add it because most users aren't savvy enough to understand what is happening and will uninstall your browser in response"). But I can't actually see anything stopping a given user agent from choosing to offer that as a development feature for a specific domain, which would be pretty swell.
I think we will never have enforced static typing in Javascript, because of legacy code.
The solution is to use something higher level. Maybe Elm.
If you don't want to this, you can still build your own real types, that's the beauty of JS.
We’re conditioned to expect there will be a compilation step between our source code and the code that runs in a browser. That forces many decisions about how we structure our projects and the kinds of tools we can use to deliver the software we write. Minimizing or eliminating the reasons why folks might need that build-the-code step between the code they write and the code their users run opens up doors and new ways of writing and delivering software, and that’s exciting!
Think, for instance, what would it take to get something like the TypeScript type checker in Chrome’s devtools? A first step would be to adopt the type annotation syntax.
not sure what typechecking inside chrome would add....
maybe it could be used for faster js execution like how asm.js works
It’s true that there are some optimizations done in the build step that benefit end users, and folks will probably (correctly) continue to choose to minify, tree shake, bundle + bundle split, eliminate dead code, etc. for serious applications.
But to be able to write a modern web app without having to npm install a single module would be stellar! And it’s becoming more and more possible. How do you teach someone how to write a JS project in 2022? I imagine it starts with, “Well, first you’ll need to install node and npm - that’s gonna run JavaScript on your computer but don’t mind that much for now. Now we’ll install some dependencies required to build your code…” and so on. It takes a while and many conceptual hurdles to get to the part where someone can run the code they wrote in a browser.
85% of the typescript libraries I have run into output either old CommonJS or es2015. There's other changes too often.
But I like it for another reason. The single most frustrating thing for me in JS is the lack of operator overloading. Matrix operations become so ugly if you can't use infix operators. If you do complex graphical calculations it is really important that the calculations remain readable.
Custom operators and operator overloading require type-dependent dispatch. The types could be known at compile time in TS. But the developers will not add any such feature, unless JS has it. One of a few prerequisites seems to be that JS gets type annotations!
But honestly it seems I would have to wait until JS becomes TS, before we can overload operators. Maybe it is more realistic to add this via babel or so.
This is a wrong assumption. There are lot of smartphones that do not get updates and have browsers that can be several years old.
Therefore transpiling and polyfills are not going away anywhere soon.
Of course, supporting different browsers can insignificantly increase development costs. It might be impractical to try to support Internet Explorer 7. A safe and reasonable choice would be to make sure that site looks and works perfectly in any browser released 5 years ago and is usable in a 10-year old browsers.
Obviously there are cases when this rule can be amended, for example, if you are making a game requiring a fast GPU and a mouse, then you can ignore smartphones and old browsers. But for a general website, like a corporate website, an online store, a social network, this seems like a sane default choice. You can extend support to 12-15 years old browsers if you feel confident in your skills.
For many smaller projects that bundling step may then simply be `deno bundle index.js` or similar.
> The proposal here differs significantly from Python's types, as the types in this proposal are entirely ignored, not evaluated as expressions or accessible at runtime as metadata.
So guess sorta prior art but quite different.
Reading the TC39 minutes for this proposal makes me think it’s highly unlikely that the approach as outlined here will go anywhere.
It would greatly reduce the need of those crazy building tools nowadays. Now we have HTTP2, if only we can write and serve a bunch of TypeScript files directly. Be it browser, Node.js or Deno, you could use the same script file without setting up M*N different webpack.whatever.config.js files.
And it will also open up the possibility of optional runtime type checking which JavaScript as a glue language really needs.
TypeScript has been very cautious about adding non-JavaScript features, and kept its promise on JavaScript compatible, so I don't see big problems merging them. It's just people will need to figure out a spec to formalize the type system for TypeScript.
The only risk is there might be clash of the communities. But it also might get us great results where the whole community working on a great project together.
Javascript as an untyped build target is fine. I'm opposed to adding (ignored) type hints to Javascript because they'd just end up rebuilding Typescript, but done poorly.
Has additional context on this proposal and has previously been linked here.
Its even like "functional", you can turn it on or off at will, it can even do regular expression tests to validate string parameters.
I partially copied it for Javascript, https://www.npmjs.com/package/type-czech, it even runs in JsFiddle https://jsfiddle.net/steen_hansen/1Lshcept/?Example-Contents
It's great to see such developer-friendly compatibility & adaptability.
Top level comments so far (I have skipped two top level comments):
"I don't want this." "I'm not sure this will help solve any of our problems." "Sounds like a bad idea" "Nahhhh lets get the [non-type related foobar] proposal to land" "This is a wrong assumption." "Just merge with Typescript already" "there will be a flame war"
Mercy! Be happy!
that's why it's not just important that we get "something", but we get it right.
And what "mess" is this? Again I think my previous advice is pretty on point: "Be happy!" Everything has only gotten better, from my perspective. That TypeScript exists & has grown up is yet more proof that incremental, ongoing, progressive advancement is amazing. I think if we'd tried to make everything all at once, it would have been a disaster.
> once this is out there, there will be code using it in the most incorrect way it can get away with, and no one will want to break that code later on.
This is a spec to let various typechecks be applied, but doesn't specify any specific type-system. I have a hard time visualizing whatever scary situation it is you are imagining. This seems low risk.
Would you accept the idea that the language has actually gotten worse? What would it take to convince you?
arguments.
i've been doing this for over two decades, & the ability to sling async functions, w3c streams, abortcontrollers, modules, optional chaining,... everything is so kick ass better. my resistance to being convinced is going to be high, but heavens yes i'd love to entertain something higher & more illuminating than the general retrogressive cassally slanderous backhanding this language endlessly endures.
My argument is essentially that as the language has become more complex, it has become harder for more junior colleagues (and actually most programmers) to use the language effectively.
Do you buy the idea that a language might be better if it were designed to guide the user towards success? Or do you think it’s better to just throw everything possible into the language, warts and all?
> w3c streams
I know what a stream is, and I know the W3C is. What is a “w3c stream”?
> modules
My experience has been that the implementation of this idea in JavaScript has been extremely fragmented.
People may not fully realize this, but the problem with the “just standardize TypeScript” suggestions is that TypeScript is a fast moving target. This is actually well argued in the proposal: lots of meaningful innovation is still happening in that space with more precise checks, which also means that small incompatibilities happen from version to version. That’s okay if we’re talking about dev tooling that a team can choose to upgrade at their own pace. It would be really bad to have browser upgrades affect the functionality of existing websites.
This is long long overdue. Silence about this cavalcade cannot go on imdefinitely. This reaction you are having seems way way out of line for some pretty basic reflection.
How else might we try to meta-attend to our social problems?
Not by haranguing forth on HN, a site that's explicitly not for that kind of discussion.
If you want JavaScript to enforce types in the browser that is a larger discussion.
it also means we dont have armies of projects downcompiling to es2015 (unperformant) and/or cjs.
This is total revisionism. Using JS to program anything substantial was a total nightmare in decades past. I've been building websites since the early 2000s, JS is more ergonomic and capable now than ever before IMO.
https://news.ycombinator.com/hidden
when logged in
To continuously add features and complexity to JavaScript makes getting started with web development that much more cruel and arduous for our more junior colleagues.
If you like types (and personally — as someone who for the past several years has almost exclusively written Haskell and Elm professionally — I do), why not just pick a different language that has the features you want and compile it down to JavaScript?
I have a perception (and I'm sure some would argue it's inaccurate) of the web development community that likes to pat itself on the back for being smart enough to use JavaScript's [relatively] new spread operator, but at the same time whinging about Elm because its syntax looks weird.
It's probably more like that meme image from some TV show:
Elm user: I feel bad for you.
Enthusiastic JS/TS user: I don't think about you at all.
Always funny to see “memes” evolve outside the original context.
[ Personally I like Natural units, ie. one of the systems where c = 1 like Planck or Stoney units. These are of course completely impractical for everyday use, but hey, what's not to like about the simplified equation E = m ? I also want French Revolutionary Months (Fructidor is a much better name for a month than "September" is) and the use of Kelvin rather than stupid °C with an arbitrary zero point ]