tc39 / proposal-type-annotations

ECMAScript proposal for type syntax that is erased - Stage 1
https://tc39.es/proposal-type-annotations/
4.23k stars 46 forks source link

This proposal can introduce misunderstanding about JavaScript's dynamic type system #62

Open sundaycrafts opened 2 years ago

sundaycrafts commented 2 years ago

I don't have any degree in CS nor am familiar with JavaScript engine implementation. But I believe that JavaScript has a dynamic type system, not static.

So, as I noticed in the title, this proposal can introduce misunderstanding about its type system.

I completely agree TypeScript or Flow is useful to build a massive application. But I don't think it is a good decision to introduce the mismatched concept into the core.

orta commented 2 years ago

This proposal would mean that JavaScript would allow for opt-in gradual typing, similar to Python or Ruby. Not that JavaScript would become a statically typed language.

sundaycrafts commented 2 years ago

Thank you, now I have clear the point of this proposal.

It seems this proposal is a big game more than I expected.

Honestly, I can't imagine how to mix static typing and dynamic typing seamlessly. Has that succeeded in other languages?

I guess even TypeScript's type system has room for improvement so I think it's not too late to wait for other altJS type systems like TypeScript to be more mature.

And also, I don't like (yes, this is just my feeling, not logical) that there are many "options" because I believe that it can make the language concept blur.

I want to know you guys' opinion about this point.

orta commented 2 years ago

If you've used TypeScript or Flow (or JSDoc comments for tooling) then you already may have a sense of what a gradual type system feels like. A mix of being able to write code without a lot of type-specific syntax, and then in areas where you want more tooling you use more types. The 'gradual' word is that the amount of typing applied is different within the codebase.

In contrast, a more static language like Java/C# requires the entire project to be very well specified in advance. There are advantages and disadvantages to both. However, there is a lot of existing JavaScript, and you very likely want to re-use some of it - and so a gradual type system works well when you have parts of your codebase which may have no type definitions at all.

Python and Ruby seem to be doing pretty well with their implementations of a gradual type system.

WRT to TypeScript's maturity, it is 10 years old in October - but there's still a lot of JavaScript concepts which TypeScript does not describe well and JavaScript is a moving target because the language evolves every year. It's important to note that this proposal makes a gap for TypeScript or any other type system to fit. The proposal is not specific to just TypeScript.

fabiospampinato commented 2 years ago

This proposal would mean that JavaScript would allow for opt-in gradual typing

This sounds very misleading to me. This proposal is for types that don't do anything. Whether those types can be turned in the future into types that do something is out of the proposal entirely.

If that's the end goal why not propose that? This looks very much like a "let's do something and hope for the best" kind of approach.


It seems misguided too, if the idea is that the full proposal wouldn't be accepted why should we accept this? If that's the idea it feels like a way to trick the committee into allowing something without fully realizing that it will constrain their choice in the future.

giltayar commented 2 years ago

This sounds very misleading to me. This proposal is for types that don't do anything. Whether those types can be turned in the future into types that do something is out of the proposal entirely.

If that's the end goal why not propose that?

The idea is for them to be there so that types can be enforce at build time by an external tool, but not at runtime by the JavaScript runtime (e.g. browser). And we have examples of very succesful system that does exactly that: enforces types at dev time and not at runtime. They're called TypeScript and Flow.

fabiospampinato commented 2 years ago

And we have examples of very succesful system that does exactly that: enforces types at dev time and not at runtime. They're called TypeScript and Flow.

It's interesting that you mention this because I never heard anybody complain that they can't use TypeScript or Flow today because of browsers not stripping out types. Who wants to use TypeScript, me included, can already do that. Same for Flow I'd imagine.

Besides it's not like 90%+ of existing TS repos would even fall under the strict syntax that this proposal proposes anyway, like which project doesn't use type guards for example? A major percentage of projects that ship for the browsers nowadays use JSX, that's just not covered by the proposal and with no intention to cover it in the future, enums are not part of the proposal etc.

Like I don't understand who is actually going to use this and why it would be a good idea for those hypothetical people to use this instead of just using a bundler, which they probably (should) want to use anyway for purposes like minification.

fabiospampinato commented 2 years ago

By the way another alternative to this is having TS output sourcemaps that include types. That sounds like a much more natural and reasonable why to solve the problem of seeing types that don't actually do anything in the devtools.

That would move the problem to TS, it wouldn't complicate the spec for something that doesn't do anything at runtime, it leaves us free to use that syntax for something else in the future, it leaves future JS+Types languages free to implement types however they like, it doesn't need to be approved by anybody in TC39 etc.

wparad commented 2 years ago

I feel like this is a fallacy of experience:

A major percentage of projects that ship for the browsers nowadays use JSX, that's just not covered by the proposal and with no intention to cover it in the future, enums are not part of the proposal etc.

What's major, 51%, definitely not, 20% surely not, whether or not something will be covered in the future has zero importance for deciding whether or not include aspects in the proposal. We should use concrete justifications on the value delivered versus the cost of delay. Do we need to do it now, probably not, can we do it later, definitely.

fabiospampinato commented 2 years ago

whether or not something will be covered in the future has zero importance for deciding whether or not include aspects in the proposal

I strongly disagree with this, if hypothetically less than 1% of existing projects would fall under this strict syntax that's a huge red flag to me. And maybe there's a reason if most projects don't already use this subset of TS, again: who doesn't use type guards, really?

I don't have any hard numbers, I'm just guessing here, IMO it'd be good to check open source TS projects for this and actually measure something, the burden of that should fall on however is proposing this proposal IMO.

Do we need to do it now, probably not, can we do it later, definitely.

I think the bigger question is: do we even want to do this at all? Like obviously this is a big change to the language for no runtime features at all, if I had to vote on this I'd think long on hard on what the upsides actually are.

josephrocca commented 2 years ago

The idea is for them to be there so that types can be enforce at build time by an external tool, but not at runtime by the JavaScript runtime (e.g. browser).

Then why does this need to be baked into the JavaScript language? If they're going to be stripped out by build tooling during minification, then the browser never sees the types anyway.

It seems like what people actually want here (at most) is just a TypeScript checkbox in DevTools, or something like that - not a fundamental change to the JS language itself, especially given that this change uses up syntax which would make it much harder to introduce actual gradual typing to JS in the future.

giltayar commented 2 years ago

It's interesting that you mention this because I never heard anybody complain that they can't use TypeScript or Flow today because of browsers not stripping out types. Who wants to use TypeScript, me included, can already do that. Same for Flow I'd imagine.

The question is: do we always want typescript (and flow) to be separate languages? I believe the fact that much of new code today is written in TypeScript and not JavaScript is important. It's a sign that the community wants types. And the fact that they chose TypeScript and not ReasonML (which also has types and transpiles to JS) and other non-js languages, is indicative of the fact that they still like JavaScript. They just want types in it.

So, yes, we can just ignore this trend. But that will mean that people will stop writing JavaScript and use TypeScript instead. I personally do not want that. JavaScript is a vibrant language, and an evolving one. And the community has spoken: they want types in the language.

Besides it's not like 90%+ of existing TS repos would even fall under the strict syntax that this proposal proposes anyway, like which project doesn't use type guards for example? A major percentage of projects that ship for the browsers nowadays use JSX, that's just not covered by the proposal and with no intention to cover it in the future, enums are not part of the proposal etc.

The goal of this proposal is to have most of the TS code pass with no or minor modifications. And the fact that Microsoft is behind this means that they will encourage developers to slightly modify their code to conform to the restrictions of the final syntax of this proposal. (And has been said elsewhere, it is almost sure that type guards will be incorporated into the syntax in one way or another).

Like I don't understand who is actually going to use this and why it would be a good idea for those hypothetical people to use this instead of just using a bundler, which they probably (should) want to use anyway for purposes like minification.

I would. So that I can start using JavaScript like it was used in the past: without any tooling. As simple as it can. In Node.js, that is the end. And in browsers? Well, yes, the last step would be to bundle/minify. But not in dev, where 90% of my time is spent.

In this sense, the proposal complicates the syntax of the language, but simplifies the tooling tremendously.

fabiospampinato commented 2 years ago

The question is: do we always want typescript (and flow) to be separate languages?

Probably? Imagine if this question got asked after the first JS+Types language got developed and we spec-ed it, now we'd be stuck forever with something that we might not even want in the end.

I like TS, I use TS every day, but keeping the door open potentially for something better to come is much more valuable to me than having an additional syntax for comments that don't do anything added to the language.

And the community has spoken: they want types in the language.

Yes, and I'm having them today by using TS, this proposal doesn't add types to JS, it adds another syntax for comments that don't do anything. Which is something we already have by the way, it's called JSDoc.

Whether comments written that way can be turned into something useful in the future it's completely outside of what this proposal is proposing. Maybe it will happen, maybe not. If it doesn't happen the value in this proposal is negative as far as I'm concerned.

I would. So that I can start using JavaScript like it was used in the past: without any tooling. As simple as it can. In Node.js, that is the end. And in browsers? Well, yes, the last step would be to bundle/minify. But not in dev, where 90% of my time is spent.

In this sense, the proposal complicates the syntax of the language, but simplifies the tooling tremendously.

Maybe I'm blind but I don't see this massive simplification at all. This is a problem that has been solved over the years without messing with the spec and constraining our future choices one bit.

sundaycrafts commented 2 years ago

I guess people who use TypeScript (like language) want to use TypeScript NOT JavaScript, and people who use JavaScript want to continue to use current JavaScript. If TypeScript people are feeling pain, that is not solved by adding a type comment (that is not core) but adding more strong type checking.

Actually, I haven't ever seen people using TypeScript without build-time type checking as far as I know. And also no one wants to use TypeScript to write a chunk of small code to run in the browser (technically, I saw 2 or 3 guys want to do that though) — that is originally a major use case of JavaScript.

IMO so the solution is can use TypeScript in the browser directly (or change JavaScript concept more statically), not modify JavaScript to mimic TypeScript.

By the way, personally, I like both languages JS and TypeScript and it is welcome that the JavaScript goes more statically. I just want to clear the point of this proposal. Is this proposal a milestone for JS to be more statically?

wparad commented 2 years ago

@sundaycrafts :100: YES! If we want types in javascript, we should add real types, and do it the right way. Not this hack way.

portableCoder commented 2 years ago

Thank you, now I have clear the point of this proposal.

It seems this proposal is a big game more than I expected.

Honestly, I can't imagine how to mix static typing and dynamic typing seamlessly. Has that succeeded in other languages?

I guess even TypeScript's type system has room for improvement so I think it's not too late to wait for other altJS type systems like TypeScript to be more mature.

And also, I don't like (yes, this is just my feeling, not logical) that there are many "options" because I believe that it can make the language concept blur.

I want to know you guys' opinion about this point.

This unneeded skepticism is why JavaScript is the way it is today. If this all was such a bad and unnecessary idea, I don't think most libraries out there would have typescript support. All languages of scale should be statically and strongly typed. It's an age old proven fact.

sundaycrafts commented 2 years ago

This unneeded skepticism is why JavaScript is the way it is today. If this all was such a bad and unnecessary idea, I don't think most libraries out there would have typescript support. All languages of scale should be statically and strongly typed. It's an age old proven fact.

First of all, I completely agree with your opinion. I never use pure JavaScript in my business project.

Every pain of people who use TypeScript comes from it is eventually transpiled into JavaScript. BUT, TypeScript guys don't (have to / want to) stick to the JS world. Because they want to deliver a robust product via a browser, no matter how.

That fact (or just my guess) indicates that JavaScript and TypeScript have a different use cases. And JavaScript's main use case is originally writing small code chunks, and this use case is still first priority, right?

wparad commented 2 years ago

I've seen plenty of real world production scenarios using javascript. I don't think we need to stipulate the "main use case" and we should probably stay away from assuming it is "small code chunks" and definitely avoid assuming "it is only the transpiled output". the latter in the fallacy becoming this repository, while I shutter to think the former also becoming a second fallacy of the community.

Javascript is its own language with a huge community and tons of apps written for both node, the browser, and the like. Throwing out things like this

All languages of scale should be statically and strongly typed. It's an age old proven fact.

This is just a hot take and should be treated as trolling. We should focus on adding value where we can, and not make generalizations or toss out incendiary words, it's not helpful. It's great to say "types in javascript is the direction we should go", and with that, let's add types to javacript, let's not add "types as comment" hacks.

portableCoder commented 2 years ago

This is just a hot take and should be treated as trolling. We should focus on adding value where we can, and not make generalizations or toss out incendiary words, it's not helpful. It's great to say "types in javascript is the direction we should go", and with that, let's add types to javacript, let's not add "types as comment" hacks.

It's not a hot take, it's THE take. It's what the majority believes in. If that wasn't the case we wouldn't see such widespread typescript adoption in the front end land, and we wouldn't see widespread adoption of other strongly typed language-based ecosystems such as spring boot, .net, rust(actix),django in the backend (some of these are far more popular than node, might I add) . Anyhow, trying to make a language statically analyzable isn't a hack, it's far less of an effort compared to adding actual types and runtime type checking in js, and more importantly it would break the web. A total language re-design isn't possible, that's why we use typescript and downlevel compile it to js. This proposal is super easy to implement and would instantly benefits tons of people (especially beginners) make their code robust and more deterministic without a build step.

test137E29B commented 2 years ago

My opinion is this should be left to external supersets like Typescript. JavaScript, node especially, is very good for doing something fast because you don't really need to worry about typing everything, setting up a build and so on just to run a simple script on some files.

I think JavaScript is much more open and easy to learn because of the dynamic types - it seems easier to new developers (from personal experience when I was learning). You can gradually add types with Typescript, as you gradually learn it.

It appears to me that what's really being asked for with this proposal is just to be able to run typescript in client and server environments without a build step to transpile or remove comments - which can already be achieved and shouldn't require changes to core.

Gotterbild commented 2 years ago

Some of the commenters above mentioned majority if people using Typescript and majority of libs support Typescript.

I admit that second one can be truth. But the first one is definitely not.

If you use Typescript and all of your friends, colleagues and sources you read, watch, etc. use it - that's just your information bubble. Personal experience shouldn't substitute statistics.

Just in case I'll mention State of JS is not correct statistics. It is statistics for people willing to participate in State of JS. Web Almanach is statistics.

My opinion regarding the proposal is it will create a lot of confusion and misunderstandings for both JS and TS people. Both of them could have wrong understanding if what code is doing.

It sounds like a better idea to keep JS and TS separate. If someone wants to have TS in browser, then it's better to support TS in a whole and explicit way (by using .ts file extension).

There's an opinion that sounds like TS people are just not experienced enough to use pure JS. And while I understand that this is not entirely true, but it is true to some extent. At least for me and my team it is. We consciously use pure JS for two big and one smaller projects and didn't have any issues that TS could solve for us. We use JSDoc however, but it's coverage is about 10%.

At the same time I totally understand the value of TS for bigger teams.

But I also understand the value of JS being a simpler language to learn.

And another point. To my surprise people discuss their developer experience and doesn't think about users. And for users the new syntax will bring absolutely no benefit with a bonus of worse performance and higher battery drain by browser. I mean both resources spent on cutting out those type "comments" out and higher bundle size.

As a conclusion, I don't think this proposal should be accepted.

chen-ye commented 2 years ago

It appears to me that what's really being asked for with this proposal is just to be able to run typescript in client and server environments without a build step to transpile or remove comments - which can already be achieved and shouldn't require changes to core.

Maybe I'm missing something, but how are you able to run typescript in the browser today, without transpilation or tooling?

chen-ye commented 2 years ago

FWIW, my opinion is that adding support to the core language for ergonomic type hinting is a logical progression of the language.

As JavaScript has matured, a number of features that have formerly required transpilation or relied on convention have become or are becoming native parts of the language--such as es-modules and import maps. This hasn't been without pain (again, es-modules), but ultimately, IMO, has been more of a pro than a con:

Type-hinting is an even better candidate for the core language--it lets developers and codebases opt-in to typing in a lightweight, incremental fashion, instead of needing to switch languages and significantly modify their build system--or introduce one in the first place. It's worth remembering that while TypeScript is quite like JavaScript, it's not simply 'JavaScript with types'--especially since the compiler defaults to downleveling code to ES5--and using TypeScript can still prevent one from adopting new language features for quite some time--such as node esm packages. The prevalence of TypeScript within the ecosystem indicates the desire for type-hinting, and I think that making it a native part of the language actually reduces indirection and complexity, and thus confusion.

Finally, the adoption of non-runtime-enforced type-hinting within Python 3 demonstrates both a precedent for something like this, as well as an empirical look at its impacts and pitfalls. Anecdotally, I've seen nothing but benefits--we've been able to make drive-by improvements to old code and have caught a number of bugs in the process, and there's never been any misunderstanding of what the feature does (and doesn't) do. I'd be curious however if there is a more comprehensive postmortem analysis of the feature--my casual searching didn't reveal any.

guitarino commented 2 years ago

@giltayar

The idea is for them to be there so that types can be enforce at build time by an external tool, but not at runtime by the JavaScript runtime (e.g. browser).

So, correct me if I'm wrong, but are you saying that the type enforcement should happen at build time, while stripping types away should happen at runtime? In that case, I'm wondering, if enforcement still requires a build step, what is the benefit of not stripping types away at build time as well?

I believe the fact that much of new code today is written in TypeScript and not JavaScript is important. It's a sign that the community wants types.

Definitely. However, if I understand it correctly (and please feel free to let me know if I don't), this proposal does not add types to JavaScript. Instead, it limits the future JavaScript type syntax to that of TypeScript. Is this correct to say?

Shouldn't the actual future JavaScript type system proposal define the new syntax, based on the features that are going to be added to the type system, rather than being prematurely limited by a proposal such as this?

Even though I completely agree with the sentiment that types are in the future for JavaScript, it currently seems to me that the only beneficiary of this proposal are Microsoft and TypeScript dev team (I am open to being shown otherwise), since the proposal would guarantee that TypeScript wouldn't need to change and adapt if JavaScript was to introduce a proper type system.

I believe that there may be an even more harmful outcome of this proposal: prevention of the future proper built-in type system in JavaScript. JavaScript is built on the idea of strong backwards compatibility: every valid old JavaScript program will always be a valid JavaScript program. This implies that, if this proposal is to go through, this code:

interface Person {
   this is ignored
}

Would become a valid JavaScript program. This implies that future type system would not be able to use interface syntax for the purpose of type-checking, since this program must always stay valid, and the JIT compiler must continue to ignore the interface body. It would make things quite difficult for the future type system, because it would have to work around these limitations and would possibly result in double type syntax: one that's being ignored by the compiler, another for actual type definitions / type checking.

I believe this is a serious concern that cannot be ignored now, nor would be ignored by members of TC39.

orta commented 2 years ago

Yep:

interface Person {
   this is ignored
}

Would be legal JS after this proposal, because it's not on the JS engine to decide how to interpret the type definitions.

With respect to the rest of your post, I think you probably will want to read https://github.com/giltayar/proposal-types-as-comments/issues/45 as that is an issue focused on whether this spec could impede a standardized type checking mechanism in JS.

giltayar commented 2 years ago

In that case, I'm wondering, if enforcement still requires a build step, what is the benefit of not stripping types away at build time as well?

Not stripping types away at build time has the same benefit of not stripping away indentation at build time: when developing the code, you want the source code to stay the same and not change, so you can debug and deal with errors more easily. It is only when you deploy to production that you want to strip away everything.

Instead, it limits the future JavaScript type syntax to that of TypeScript. Is this correct to say?

No. It's much larger than that. While there is some limiting going on here, it is not to TypeScript (or Flow, or Hegel), but rather carves out "syntax space" where type systems can define whatever syntax they want. Which is why the proposal is compatible with TypeScript, Flow, and whatever type system you can define against the wide constraints.

This implies that future type system would not be able to use interface syntax for the purpose of type-checking

In the proposal FAQ, there is an explanation of just that question. The answer, in the end, is, no, it would not limit future specific type checking by JavaScript.