TypeScript versioning is a joke on Semver that Daniel and team love to play. They go from 3.9 to 4.0 because as you all know 3.10 would be impossible!
Every version of TypeScript is potentially a breaking change so if they wanted to be pure Semvers we would've been at TypeScript version 100 or more which could make people feel overwhelmed about being behind with their current version.
As always a great release! Congratulations to the team! We love TypeScript at my team.
I've never seen someone who wants to go back from TypeScript to plain JavaScript. Design decisions made about structural comparison and not much focus on correctness made TypeScript an easy forgiving type system that hold developer's hand without being a pain in the bottom. The way TypeScript interacted with the community and received feedback also helped its success.
Major version bumps were never a problem. Semver-wise, the only conceivable problem is in introducing backwards-incompatible changes in minor or patch version bumps. By bumping the major version, semver-wise it just means "be aware that your software might break if you upgrade blindly to this version." No one will die if you expect problems but end up having none.
The point of semver is that it's a kind of contract where you implicitly summarize the nature of the changes you introduce in a release in its version number. You provide contextual hints through the version number.
> Ok, but how do you know that a change (possibly a bugfix) in your code will break something (maybe a weird, broken thing) that I depend on?
That would be unintentional though. If that happens to you report it as a regression and most developers will give it super high priority and even release a hotfix to deal with it.
There's a big difference between accidental breakage, which is always a bug, and intentional breakage where it's reasonable to give some type of notice to people consuming your platform / API.
Yeah I think my biggest pain with typescript would be the compile times in larger applications... Although I have very little reference to other compilers with the same code base. I can see why they ditched it
If you take to time to set up incremental compilation, it's really quite fast. For reference, updates to the vscode repo (~5k files) take generally <300ms to recompile, and even incrementally updating after pulling in a batch of hundreds of commits takes only ~10 seconds.
It's concerning to me that the deno folks chose giving up on type safety over figuring out how to set up their development environment to better meet their needs.
You know, software projects are under no obligation to follow semver. I abhor this newfound conformism in tech.
Plus, after nearly a decade of programming I can safely say the benefits of semantic versioning rarely materialize. 99% of the time you just upgrade to whatever latest is, major or not, and deal with it. For all I care they could be releasing Typescript v736.8B
The difference is that I can update all dependencies without having to verify whether they contain breaking changes, because I can just look at the number.
Conformism helps us think less. Imagine if every website had their own way of scrolling or logging in. Press T to login. Triple click here.
Semver helps me update 10 dependencies in 5 seconds without opening any release notes.
Developers are under no obligations, but one should not go out of their way to make others’ lives harder. Just use semver.
Not exactly 10 dependencies, but I do that many times by using version ranges like ^1.0.0. So to answer your question: What you are updating and why... mostly patch and minor versions that include vulnerability and performance fixes. And I read release notes... but the number gives me a good idea what to read in more detail.
Now the problem of TS not following the convention is that many projects have ranges like ^3.7.1 in their package.json without knowing that a simple install removing package-lock may break your build because 3.8 and 3.9 have breaking changes in it.
That is precisely what I mean about not materializing, reality is not like that. Maintainers make mistakes, are not diligent about following semver, and after enough “minor” upgrades that break everything you simply lose all trust in the numbers.
SemVer is nice but not nescessarily - I'd rather a project not follow semver but have a clear deprecation cycle they follow all other things been equal.
version n, we are going to remove foo
n+1 foo is marked as deprecated
n+2 foo is removed.
That I can work with since it gives me a change to refactor with clear ideas of what will break.
The symfony team get my absolute respect for the way they handle this over in PHP land,it gives me a high degree of re-assurance that we can reliably shift versions with minimal friction since they are alerting me though deprecation notices that I can then go resolve.
Versioning is a facet of documentation. SemVer is not the only way, but it's a widely-understood convection and quite logical.
The core issue generally comes down to: "If I upgrade, what do I have to do?"
If you have good release notes and upgrade guide(s) that don't assume every user is following each release closely, that's probably ok.
If your release notes are non-existent or just an export of your commit messages or ticket titles, SemVer helps cut through the noise.
Going from 1.2.34 to 1.2.85? No second thoughts. To 1.5.2? I'll probably look at what was new in 1.3.0, 1.4.0 and 1.5.0 just to keep updated. To 3.2.0? I'm going to be super cautious and assume I have a bunch of changes to make, and hopefully there's a 1.x to 3.x guide, or at least 1.x to 2.x and 2.x to 3.x.
In the worst case, it compiles fine but a bunch of stuff breaks at runtime. With nothing but SemVer, I'm at least prepared to test extensively. If I go from 1.2.34 to 1.2.x and get a bunch of runtime breaks, my first reaction is going to involve profanity and be something along the lines of "time to replace this garbage library with something better."
As library authors, we're under no obligation to use SemVer, produce release notes, documentation, or do anything else. The nice thing about SemVer is it's basically zero-effort yet provides massive benefits to users, especially if everything else I mentioned is lacking.
If it isn't for a meaningful versioning scheme, how is a version number useful at all? Why not just go version 1, 2, 3 and keep incrementing?
People can easily guess that patch version bump is safe to apply as it only fixes stuff and apply minor version bump if you want new features which won't break your current deployment and be cautious of any major version bumps.
Not that every semver oriented apps closely follow that but it does help users understand if they want to install the new version or not without digging the entire change log.
> I've never seen someone who wants to go back from TypeScript to plain JavaScript.
I do, as mentioned in several threads, I only use platform languages in production, which on the browser means JavaScript + whatever targets WebAssembly.
For something like Angular, then Angular is the platform, written in Typescript, with all the tooling for a seamless development experience, then I make use of Typescript.
The less layers to debug, FFI libraries that I don't need to write (type libs), endless list of compiler modes to read through,now double way to declare private members,... the better.
Still hope for Typescript to turn into WebIDL, but most likely it won't ever happen.
As a new developer, typescript is awesome for me. When developing for web, there seems to be all sorts of “types” that I don’t get know or fully understand. By forcing types, I can be sure the data I am passing is what I want.
I'm disappointed that it still doesn't incorporate a tool for one common case, runtime type checking. Node.js REST servers receive a lot of JSON objects and it would be nice to automatically check that they actually follow type.
There are several aftermarket add-ons (io-ts, runtypes, class-validator) but they all seem to impose extra steps or rewriting code -- and different projects will use different ones. It seems like it should be something they can build into the language. I'd rather have one good standard than a dozen alternatives. (Can you guess I come from a Java background?)
That is outside of the scope of TypeScript, which is to be a statically typed superset of JavaScript with no runtime cost.
It's easy enough to write a runtime type checking library; I wrote a tiny one that I use in basically all my projects: https://npmjs.com/package/narrows
I understand that it’s not TypeScript’s job at the moment, but it’d be great to enable runtime checks with the flick of a switch without typing extra code.
function upper(s: string) {
return s.toUpperCase();
}
This function could have a nice implicit TypeError instead of “undefined is not a function”
I’m not sure what you mean. My library has a `TypeOf` type that lets you extract static type information from validation functions. And calling `toUpperCase` on undefined already results in a TypeError.
> I'm disappointed that it still doesn't incorporate a tool for one common case, runtime type checking. Node.js REST servers receive a lot of JSON objects and it would be nice to automatically check that they actually follow type.
You are using the wrong tool for the job then. There are json-schema libraries made for that purpose. It has absolutely nothing to do with Typescript which is just basically a static type analyser, not a language with a runtime, since it does absolutely nothing at runtime.
I see the utility of json-schema, I just wish the schemas were beautiful and succinct like TS type definitions are.
I know one is runtime and one is compile-time, but they both allow you to specify the "shape" of a particular JSON object and verify an example against it.
I've been using reasonml lately and absolutely love it, I've been coding a non trivial application, and there is essentially no type annotations (which makes refactoring very easy). So I find it super weird when I read typescript code because there are complexe type annotations with nested generics all over the place.
Is it just that typescript needs these annotations whereas ocaml does not ? Or it's just best practices that recommend still using them explicitly ?
Typescript’s versions are just weird. I still don’t get why they don’t always increase major versions if it’s a breaking change. Who cares if it’s typescript 40 or typescript 4.0. You don’t need to be a special flake. It’s an interface that lets you know when TS upgrades are safe and when they’ll break your code. Sure most TS versions tighten the type system but there’s no harm in having version 9000.
In the world of rust, cargo does a smart thing unlike npm I.e “Avoiding Combinatorial explosion of dependencies. Cargo pulls back on npm’s model a bit: it will unify dependencies up to semver compatibility”
If typescript were a rust package, it would break that assumption really bad.
Please follow semver like the rest of the npm ecosystem.
43 comments
[ 5.1 ms ] story [ 96.0 ms ] threadEvery version of TypeScript is potentially a breaking change so if they wanted to be pure Semvers we would've been at TypeScript version 100 or more which could make people feel overwhelmed about being behind with their current version.
As always a great release! Congratulations to the team! We love TypeScript at my team.
I've never seen someone who wants to go back from TypeScript to plain JavaScript. Design decisions made about structural comparison and not much focus on correctness made TypeScript an easy forgiving type system that hold developer's hand without being a pain in the bottom. The way TypeScript interacted with the community and received feedback also helped its success.
So glad to hear that you're happy with the release, and thank you for the kind words.
The language Unison has an elegant solution: hashing the ast as the version.
This isn't rocket science.
Fix bug that doesn't change behavior nor the interface? Bump patch number.
Add feature/extend interface? Bump minor version.
Otherwise, bump major version.
That's pretty much it.
For a detailed definition:
https://semver.org/spec/v1.0.0.html
The point of semver is that it's a kind of contract where you implicitly summarize the nature of the changes you introduce in a release in its version number. You provide contextual hints through the version number.
How would you fix a bug without changing behavior? “Incorrect behavior” is the definition of a bug.
That would be unintentional though. If that happens to you report it as a regression and most developers will give it super high priority and even release a hotfix to deal with it.
There's a big difference between accidental breakage, which is always a bug, and intentional breakage where it's reasonable to give some type of notice to people consuming your platform / API.
This is a very specific case, but it can happen: https://github.com/denoland/deno/pull/6793
Yeah I think my biggest pain with typescript would be the compile times in larger applications... Although I have very little reference to other compilers with the same code base. I can see why they ditched it
It's concerning to me that the deno folks chose giving up on type safety over figuring out how to set up their development environment to better meet their needs.
Also running tests is quite time consuming of you do not run them in parallel.
I guess bazel would be a good fit with Typescript.
As for deno, I did not follow the topic but I hope they at least annotated with JSDoc so developers can get some linting.
Plus, after nearly a decade of programming I can safely say the benefits of semantic versioning rarely materialize. 99% of the time you just upgrade to whatever latest is, major or not, and deal with it. For all I care they could be releasing Typescript v736.8B
Conformism helps us think less. Imagine if every website had their own way of scrolling or logging in. Press T to login. Triple click here.
Semver helps me update 10 dependencies in 5 seconds without opening any release notes.
Developers are under no obligations, but one should not go out of their way to make others’ lives harder. Just use semver.
Now the problem of TS not following the convention is that many projects have ranges like ^3.7.1 in their package.json without knowing that a simple install removing package-lock may break your build because 3.8 and 3.9 have breaking changes in it.
SemVer is nice but not nescessarily - I'd rather a project not follow semver but have a clear deprecation cycle they follow all other things been equal.
version n, we are going to remove foo n+1 foo is marked as deprecated n+2 foo is removed.
That I can work with since it gives me a change to refactor with clear ideas of what will break.
The symfony team get my absolute respect for the way they handle this over in PHP land,it gives me a high degree of re-assurance that we can reliably shift versions with minimal friction since they are alerting me though deprecation notices that I can then go resolve.
The core issue generally comes down to: "If I upgrade, what do I have to do?"
If you have good release notes and upgrade guide(s) that don't assume every user is following each release closely, that's probably ok.
If your release notes are non-existent or just an export of your commit messages or ticket titles, SemVer helps cut through the noise.
Going from 1.2.34 to 1.2.85? No second thoughts. To 1.5.2? I'll probably look at what was new in 1.3.0, 1.4.0 and 1.5.0 just to keep updated. To 3.2.0? I'm going to be super cautious and assume I have a bunch of changes to make, and hopefully there's a 1.x to 3.x guide, or at least 1.x to 2.x and 2.x to 3.x.
In the worst case, it compiles fine but a bunch of stuff breaks at runtime. With nothing but SemVer, I'm at least prepared to test extensively. If I go from 1.2.34 to 1.2.x and get a bunch of runtime breaks, my first reaction is going to involve profanity and be something along the lines of "time to replace this garbage library with something better."
As library authors, we're under no obligation to use SemVer, produce release notes, documentation, or do anything else. The nice thing about SemVer is it's basically zero-effort yet provides massive benefits to users, especially if everything else I mentioned is lacking.
People can easily guess that patch version bump is safe to apply as it only fixes stuff and apply minor version bump if you want new features which won't break your current deployment and be cautious of any major version bumps.
Not that every semver oriented apps closely follow that but it does help users understand if they want to install the new version or not without digging the entire change log.
I do, as mentioned in several threads, I only use platform languages in production, which on the browser means JavaScript + whatever targets WebAssembly.
For something like Angular, then Angular is the platform, written in Typescript, with all the tooling for a seamless development experience, then I make use of Typescript.
The less layers to debug, FFI libraries that I don't need to write (type libs), endless list of compiler modes to read through,now double way to declare private members,... the better.
Still hope for Typescript to turn into WebIDL, but most likely it won't ever happen.
It helps all of us so much! Thank you TypeScript team :D
React 17
TypeGraphQL 1.0.0
GraphQL-Modules 1.0.0
StoryBook 6
Webpack 5
Next 9.5
It's been an awesome month for TS/GraphQL (stable) releases
My main favourite is topLevelAwait experiment
There are several aftermarket add-ons (io-ts, runtypes, class-validator) but they all seem to impose extra steps or rewriting code -- and different projects will use different ones. It seems like it should be something they can build into the language. I'd rather have one good standard than a dozen alternatives. (Can you guess I come from a Java background?)
It's easy enough to write a runtime type checking library; I wrote a tiny one that I use in basically all my projects: https://npmjs.com/package/narrows
I understand that it’s not TypeScript’s job at the moment, but it’d be great to enable runtime checks with the flick of a switch without typing extra code.
This function could have a nice implicit TypeError instead of “undefined is not a function”Yes, that is the thing being criticized here.
Not it shouldn't, since it would affect runtime performances.
https://github.com/moltar/typescript-runtime-type-benchmarks
You are using the wrong tool for the job then. There are json-schema libraries made for that purpose. It has absolutely nothing to do with Typescript which is just basically a static type analyser, not a language with a runtime, since it does absolutely nothing at runtime.
Typescript is a static code analyser, nothing more. It doesn't do anything at runtime.
I know one is runtime and one is compile-time, but they both allow you to specify the "shape" of a particular JSON object and verify an example against it.
Is it just that typescript needs these annotations whereas ocaml does not ? Or it's just best practices that recommend still using them explicitly ?
In the world of rust, cargo does a smart thing unlike npm I.e “Avoiding Combinatorial explosion of dependencies. Cargo pulls back on npm’s model a bit: it will unify dependencies up to semver compatibility”
If typescript were a rust package, it would break that assumption really bad.
Please follow semver like the rest of the npm ecosystem.