Open jethrolarson opened 2 years ago
I only updated the README, btw.
I really like that, seems much better than the complexity that this proposal in its current form would create. Easier to parse (just ignore the whole line) and keeps the actual JavaScript code clutter free.
I like it! Very Haskell-ish, and is a subtle reference to the jsdoc typings.
But it is a goal of this spec to be mostly compatible with the massive amounts of Flow and TypeScript code out there. Alternative specs were just not considered because of this goal.
it is a goal of this spec to be mostly compatible with the massive amounts of Flow and TypeScript code out there.
Adding type hints without proper type checking seems conceptually incompatible with what TypeScript's syntax makes the code imply. Copying it verbatim would just make it so that actual type checking could never be added in the future as it'd clash, would it not?
Copying it verbatim would just make it so that actual type checking could never be added in the future as it'd clash, would it not?
This has been mentioned multiple times. And, yes, as it stands, this proposal would not enable future type standardization and checking. But there are multiple way out of this problem if type checking would want to be added to the standard (e.g. a "use types"
mode).
Honesty this looks significantly less readable than the current TypeScript/flow syntax
Similar to #80
@VitorLuizC I don't think it has much in common with #80 other than it's another syntax proposal.
I suppose it's worth mentioning that it's inspired by the haskell-ish type annotations used by Ramda and other parts of the FP js community.
I have been considering making it actually "types as comments" as that is totally possible with my approach. Just change ::
to //:
or whatever.
I really think that TS and Flow used inline types not because it's better but because it's what all the other popular programming languages do. It's like putting semi-colons in languages because it "feels right". In trivial examples it makes little difference but if you do anything with HOFs and it becomes bewildering
Here's a motivating example for those that didn't scroll all the way down:
This proposal aims to separate types and terms in a way that enables comfortable use of generics, currying, and higher-order functions in a way that languages struggle with. Here is an illustrative example from TypeScript.
const compose = <A, B, C>(g: (y: B) => C) => (f: (x: A) => B) => (a: A): C => g(f(a));
Even though this is a simple function that is known as compose operator or the B combinator, due to the verbosity and complection of types and terms it is visually hard to process. Following this proposal would make it look like:
::<A, B, C>(B -> C) -> (A -> B) -> A -> C
const compose = (g,f) => a => g(f(a))
This makes it easy to study the actual code or the type independently to understand them without getting types and terms mixed up in your head.
Want to take the type for a statement and turn it into a type alias? just whack type
in-front of it.
It may well be the case that it's better for more complex cases and that Typescript (and Actionscript and Flow etc) could have been better off if they picked that syntax.
But they didn't. They all picked the convention of interleaving the types that most every other language does, for whatever reason.
Remember, the only reason this is a proposal at all is the overwhelming popularity of typescript, (and the relatively trivial spec impact of "just ignore them")
I think for this (or #80) to be meaningful, you would have to convince a significant chunk of developers to start using the syntax in a transpiler first, as unlike most other proposals, this doesn't actually do anything, so it only has meaning when easing an existing workflow. Maybe that looks like Typescript adding this syntax and pushing people to it, like a nuclear version of the cast syntax change; but I just don't see it realistically happening.
I even mostly like it, a pretty high bar, if I do say so myself! But it has the issue of being line delimited in a (mostly) sigil delimited language.
I'm personally very much in favor of something like this. I believe it to be more readable in general (obviously not to those that already are familiar with TS) and it is much easier to use a type system like this for functional programming (which TypeScript really struggles with since it began life as type system focused on object-oriented code).
For those that don't know, the inspiration for the documentation style for Ramda, Sanctuary, and some other functional oriented JS libraries is called the Hindley-Milner type system (maybe worth mentioning in the original post, @jethrolarson ?).
I also really like separating the type from the actual JS code. I think it's particularly less overwhelming to new developers and it's easy to add: you just add a line above a function and you're good to go.
I'm aware that the goal of the proposal is to basically make TypeScript code run in browsers but I'm very concerned about this proposal overlooking the needs and wants of the functional JS community in favor of a large community that just wants their thing in the browser (what community wouldn't be in favor of that?).
https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system
I also really like separating the type from the actual JS code. I think it's particularly less overwhelming to new developers and it's easy to add: you just add a line above a function and you're good to go.
I'm aware that the goal of the proposal is to basically make TypeScript code run in browsers
And Node! And Deno! People keep forgetting that... 😀 (off-topic, I know. Just a personal itch)
but I'm very concerned about this proposal overlooking the needs and wants of the functional JS community in favor of a large community that just wants their thing in the browser (what community wouldn't be in favor of that?).
It's a tradeoff. And in this tradeoff, I would prefer a proven and loved solution that a lot of the community is behind (TypeScript) than a new type system that's never been tried before and has to overcome the huge barrier to entry that is existing TS code.
Yes, I want the pure and perfect solution. But the best solution is not always the perfect one. This is the web, and the web started out as an imperfect solution. But it evolved, imperfectly. And that the end result of that evolution is most definitely not the pure and perfect solution. But it works. And it works well.
And, yes, I still do wish for a more functional/haskell-ish approach.
(Sorry, I'll stop being sentimental now ☺️)
For what it's worth this proposal does allow:
const compose:<A, B, C>(B -> C) -> (A -> B) -> A -> C
= (g,f) => a => g(f(a))
To my understanding, you can still write a type checker on top of it that works like that
It's a tradeoff. And in this tradeoff, I would prefer a proven and loved solution that a lot of the community is behind (TypeScript) than a new type system that's never been tried before and has to overcome the huge barrier to entry that is existing TS code.
I think it's a bit dismissive to say overlooking a large community is a just a "tradeoff". Functional programming is getting more and more popular in the JS world and to just say "Eh, our community is bigger so we're just gonna go ahead and not consider other developers" isn't the right mindset for creating a proposal that's going to affect everyone and the future of JS.
There are type systems, like Hindley-Milner, that have been tried before. Not necessarily in JS but it's not like TypeScript is the only proven type system. And TypeScript has been proven to work for what TypeScript works for, just saying it's "proven" is disingenuous when you're only referring to it working for what it works for (what you use it for). And TypeScript isn't a barrier to entry at all for a type system in JS since TypeScript isn't a part of JS.
This proposal doesn't sit right with me in general. This effort would be much better spent on developing a type system that works for everyone. It really just feels like TypeScript users wanting to shoehorn what they can into JS. If this goes through, it's going to kneecap any future attempt at a real type system.
@kee-oth ok, I keep seeing this response. Why do you feel this is only usable for typescript? There's no reason to think that at all from what I can see.
(Also Elm is apparently the second most popular JS transpiler now, you should look into it)
@simonbuchan To be clear, I never said anything about this only being usable for TypeScript. I do, however, believe that TypeScript is being and will be treated as the first class citizen in this proposal. This means that whatever people come up with via these discussions will be heavily favoring TypeScript, maybe not the syntax (but probably) but definitely what "space" needs to be carved out will be how TypeScript does it. If someone proposes an idea that doesn't also work with TypeScript, it will be extremely difficult to get it in, if not just already dead in the water. Other type systems will be welcome so long as they play by the rules that were set by TypeScript's needs.
This proposal will already probably be a bit different than TypeScript because of various restrictions. A TypeScript project is already not going to "just work" in the browser (or Node) so why not start fresh and work from a place that's best for JS and the larger community and not just TypeScript? A great approach for a type system would be to start from scratch with advocates for a JS type system in general and with type system experts working on something extremely ergonomic and usable for all JS use cases. The current proposal is a proposal born from advocates for a particular brand of a type system which isn't necessarily the same as developers who want a type system in JS in general. The goals are different and skewed and therefor the proposal and any solution will have that skew built in.
A great approach for a type system would be to start from scratch with advocates for a JS type system in general and with type system experts working on something extremely ergonomic and usable for all JS use cases
Funny, that already happened at least three times: Actionscript, Flow and Typescript. They all used basically identical syntax, despite having very different semantics (Flow even used Hindley-Milner). We already have the results, adding types to JS looks like this. Are there devils in the details? Of course. But there's plenty of real world examples to look at to see what actual trade-offs you're making, and the fact that the big trade-off here is the billions of lines of Typescript already out there should hardly be a reason to avoid that syntax.
Funny, that already happened at least three times: Actionscript, Flow and Typescript. They all used basically identical syntax, despite having very different semantics (Flow even used Hindley-Milner). We already have the results, adding types to JS looks like this.
I disagree. It's safe to assume all three of those projects had their own goals and objectives. Flow is the only one I think may have been actually designed from the start for general purpose JS programming. ActionScript isn't Javascript and is object-oriented. And TypeScript was born heavily leaning towards object-oriented programming and that hasn't really shaken off. So ActionScript and TypeScript's type systems reflect that.
...there's plenty of real world examples to look at to see what actual trade-offs you're making, and the fact that the big trade-off here is the billions of lines of Typescript already out there should hardly be a reason to avoid that syntax.
I don't believe there is much of a trade-off with going with something new vs something TypeScript-y. This proposal will already require codemods to TypeScript codebases to make them work. So we're not going actually have TypeScript in the browser anyway so I don't think this proposal should be shackled to how TypeScript currently is.
And TypeScript was born heavily leaning towards object-oriented programming and that hasn't really shaken off
Uh... citation needed? Typescript from the very start was only implementing existing JavaScript type behavior? They added classes, but only when it was specced by ECMA, and was also implemented by babel and the like. I think you don't have a very good understanding of Typescript and probably shouldn't be making sweeping claims about it's appropriatness here?
@simonbuchan
Here's the citation, straight from TypeScript's official website:
TypeScript began its life as an attempt to bring traditional object-oriented types to JavaScript so that the programmers at Microsoft could bring traditional object-oriented programs to the web. As it has developed, TypeScript’s type system has evolved to model code written by native JavaScripters. The resulting system is powerful, interesting and messy.
https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html
@kee-oth that's a weird statement: perhaps they meant it started internally as an attempt at aping traditional C# style types and found that modeling JavaScript behaviors made more sense, because to my knowledge no public version of typescript has had anything I would call traditional OO types.
It's probably illustrative to read the next document up from that link, the one for OO language users: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-oop.html
It spends all it's time telling you how Typescript doesn't work like traditional OO at all.
Can you point at any particular feature of Typescript that you feel demonstrates:
And TypeScript was born heavily leaning towards object-oriented programming and that hasn't really shaken off.
The only one I can think of is enums, which are basically a fancy set of constants, and not much like C#, for example.
I'm not entirely sure what you're getting at. The class syntax, in its entirety, is something unique to OOP, so any type syntax they add that focues on class syntax is a feature that's specifically tailored towards OOP. So, this includes things like inheritance-related type-checking, abstract classes, public, private, protected, etc.
Are these features implemented in a way that's different from how it's implemented in a "traditional" OOP language like Java or C#? Sure. TypeScript has limitations, so they can't exactly emulate the behavior of C# and Java, and they wanted to make that clear. But, non-traditional OOP doesn't mean non-OOP.
In the end, this is probably just a debate over semantics. What you're defining as OOP is probably a little different that what that author may have had in mind, and that's fine. I think @kee-oth's point still stands though, which is the fact that TypeScript does provide a ton of support for OOP, and less support for those from a more functional background. I'm honestly not sure how much TypeScript could do to support a more functional type-system, they're severely limited in what they can do. But, we might not be as limited in this proposal, so it's possible we could consider things that TypeScript would not have been able to consider, things like type classes, or algebraic data types, etc. TypeScript's success makes it a great starting point, but I see nothing wrong with exploring some of these other ideas as well.
@theScottyJam (and @kee-oth I guess) https://en.m.wikipedia.org/wiki/TypeScript
TypeScript developers sought a solution that would not break compatibility with the standard and its cross-platform support. Knowing that the current ECMAScript standard proposal promised future support for class-based programming, TypeScript was based on that proposal.
Typescript has a few ideas from pre-1.0 days that were not based on standards work, but it seems as they settled on the final behavior and as it took off, they have been extremely careful to avoid adding any behavior or syntax other than erased types. Enums and modules are notable exceptions, but are hardly particularly OO.
After having a long think on this. I don't think my proposal here is good because it's proposing another specific type system. Even though I'd prefer that kind of type syntax, I think that this spec should be completely agnostic of what the metadata is doing and merely provide a way to inline arbitrary metadata within source code with some kind of way of designating what system is being used for that metadata. #80 I think is moving that direction so I've created a branch that explores that.
:: (string, string, string?, string?) -> string
function stringsStringStrings(p1, p2, p3, p4 = "test") {
// TODO
}
I like this and think it's better than this proposal, but, suggestion, what about this?..
// (string, string, string?, string?) -> string
function stringsStringStrings(p1, p2, p3, p4 = "test") {
// TODO
}
Requires literally no change to the language and achieves all the same results.
So I'm not sure what the best way to engage here is but I put together an alternate syntax that more closely accomplishes the goal of types-as-comments while addressing some of the complaints I have about languages that mix types and terms in the same space. JSDoc doesn't do this, but TypeScript does. Both have advantages, and my proposal aims to get at them.
https://github.com/jethrolarson/proposal-types-as-comments