Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(maintenance): adopt TypeScript 5.x #1672

Merged
merged 4 commits into from
Sep 13, 2023

Conversation

dreamorosi
Copy link
Contributor

@dreamorosi dreamorosi commented Sep 12, 2023

Description of your changes

This PR bumps the TypeScript version for the project to the latest available, which at the time of writing is 5.2.2.

As detailed in the linked issue, one of the main changes brought by TypeScript 5.x is a new implementation and signature for class method decorators [1][2]. This new implementation is more in line with the latest version of the tc39 proposal which is currently at Stage 3 (of 4). The same implementation however is not compatible with the project's implementation and signature due to Powertools having based its decorator on another implementation (found in Babel) that instead is based on an even more experimental stage 2 implementation.

Until TypeScript 4.9.5 (latest version of the 4.x major) the experimentalDecorators compiler option allowed developers to enable support for decorators. Without this option enabled, code that used decorators would not be transpiled by TypeScript and cause a build error. For all intense and purposes up until this version decorators were an opt-in feature in TypeScript.

With TypeScript 5.x decorators have finally become a first-class citizen and the feature is enabled by default. The experimentalDecorators compiler option is still present and its meaning can be considered as unchanged, even though enabling/disabling it yields a different outcome than in 4.x.

Starting from 5.0 setting the experimentalDecorators option to false causes TypeScript to transpile decorators according to the stage 3 implementation (aka the new one). Setting the option to true instead causes TypeScript to transpile using the older stage 2 implementation.

With the above in mind, in upgrading the project to support TypeScript 5.x we had to choose whether to adopt the new implementation or stick with the old. As many things in this ecosystem, and especially when it comes to experimental features, each option comes with its own tradeoffs.

As mentioned previously, the decorators 5.x implementation is more formally correct and for this reason our initial plan was to move all Powertools decorators to it. This is detailed in the linked issue and given the different signature it would have resulted in a breaking change & consequently landed in the next major release.

While we were able to successfully create a PoC of the new implementation based on decorators 5.x, we soon realized that the new stage 3 implementation is not supported by tools like esbuild (evanw/esbuild#104 (comment)) and its derivatives (i.e. vitest). This means that at the time of writing it's not possible to use stage 3 decorators supported by TypeScript with esbuild, AWS CDK, and AWS SAM CLI.

For this reason, and also because we rely on both esbuild and CDK to run our integration tests, we have decided to stick with the stage 2 implementation which allows us to land TypeScript 5.x support without causing breaking changes.

We acknowledge that this is not an optimal solution due to the stage 2 implementation being now outdated, however we consider this tradeoff worthy for the following reasons:

  • esbuild is widely used by Serverless developers due to it being used under the hood by both AWS SAM CLI and AWS CDK, as well as being mentioned as a recommended option to bundle and transpile TypeScript to JavaScript in the AWS Lambda Developer Guide
  • this option requires developers to enable experimentalDecorators in their tsconfig.json file which is already required for customers using Powertools' decorators, thus maximing backwards compatibility
  • the new implementation supported by TypeScript 5.x is still considered non-final and subject to change before finally reaching stage 4 and becoming part of the language.

In order to bump the TS version I also had to upgrade other development dependencies, namely: jest, ts-jest, @types/jest, typedoc (and its plugin dependencies), eslint (and its plugin dependencies). Note that I was not able to upgrade @typescript-eslint/eslint-plugin and @typescript-eslint/parser to their latest versions due to them having dropped support for Node.js 14. As soon as we start working on a release that is no longer targeting that runtime we should upgrade them (#1664).

Important

After merging this PR we will continue to listen for customers feedback and remain open to revisit the choice and discuss alternatives as long as there is significant demand, so if anyone reading this in the future uses/wants to use Powertools and also authors decorators using the stage 3 implementation and is blocked by this choice, please consider opening an issue or getting in touch via our usual channels.

[1] https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#decorators
[2] https://2ality.com/2022/10/javascript-decorators.html

Related issues, RFCs

Issue number: #1375

Checklist

  • My changes meet the tenets criteria
  • I have performed a self-review of my own code
  • I have commented my code where necessary, particularly in areas that should be flagged with a TODO, or hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my change is effective and works
  • The PR title follows the conventional commit semantics

Breaking change checklist

Is it a breaking change?: NO

  • I have documented the migration process
  • I have added, implemented necessary warnings (if it can live side by side)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@dreamorosi dreamorosi requested a review from a team as a code owner September 12, 2023 16:54
@dreamorosi dreamorosi linked an issue Sep 12, 2023 that may be closed by this pull request
2 tasks
@boring-cyborg boring-cyborg bot added documentation Improvements or additions to documentation dependencies Changes that touch dependencies, e.g. Dependabot, etc. labels Sep 12, 2023
@pull-request-size pull-request-size bot added the size/S PR between 10-29 LOC label Sep 12, 2023
@dreamorosi dreamorosi self-assigned this Sep 12, 2023
@pull-request-size pull-request-size bot added size/M PR between 30-99 LOC and removed size/S PR between 10-29 LOC labels Sep 12, 2023
@dreamorosi dreamorosi marked this pull request as draft September 12, 2023 18:01
@sonarcloud
Copy link

sonarcloud bot commented Sep 12, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@dreamorosi dreamorosi marked this pull request as ready for review September 12, 2023 18:39
@dreamorosi
Copy link
Contributor Author

Copy link
Contributor

@am29d am29d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this upgrade Andrea!

While we were able to successfully create a PoC of the new implementation based on decorators 5.x, we soon realized that the new stage 3 implementation is not supported by tools like esbuild (evanw/esbuild#104 (comment)) and its derivatives (i.e. vitest). This means that at the time of writing it's not possible to use stage 3 decorators supported by TypeScript with esbuild, AWS CDK, and AWS SAM CLI.

For this reason, and also because we rely on both esbuild and CDK to run our integration tests, we have decided to stick with the stage 2 implementation which allows us to land TypeScript 5.x support without causing breaking changes.

Let's setup a regular reminder to check the esbuild feature request for stage 3 decorators and subscribe to the issue.

@dreamorosi
Copy link
Contributor Author

I am subscribed but looking at the maintainer's comments in the issue it's unlikely they will support the feature until it reaches stage 4 but maybe they'll change their mind based on demand.

For the record: in order to reach stage 4, a feature needs to be implemented & shipped in at least two major browsers, after which the implementation will be considered final. Currently as far as I can tell only Firefox has started working on this.

Hopefully now that TS has adopted stage 3 other browsers will follow suit and include decorators as part of their 2024 plans but in the best of cases I think we are looking at 12-18 months before anything changes.

This is less than ideal, but we have to live with the decision of supporting an experimental feature and this is the best we can do with the current state of things.

@dreamorosi dreamorosi merged commit 6d2de72 into main Sep 13, 2023
29 checks passed
@dreamorosi dreamorosi deleted the 1375-maintenance-upgrade-typescript-5x branch September 13, 2023 10:56
@TheHolyWaffle
Copy link

@dreamorosi esbuild now officially supports TC39 decorators since version 0.21.0:

evanw/esbuild#104 (comment)

Can we start migrating the decorators to the official approach? It'd be handy to drop middy fully. But until decorators are re-implemented, we cannot.

@dreamorosi
Copy link
Contributor Author

dreamorosi commented Oct 11, 2024

Hi @TheHolyWaffle, yes we're aware of esbuild now supporting the new syntax however making the change will likely require a breaking change, and a major version release, on our side.

We released v2 at the end of Q1 2024 and according to our current versioning policy we officially marked v1 as end of like only one month ago.

With this in mind, unless we can adopt the new decorators in a backwards compatible way, I don't see us releasing a v3 before early Q2 2025. Between now and then, the team will be fully focused on maintaining and improving the existing features and start working on the next upcoming feature which is Event Handler as stated in to our roadmap.

We are tracking the discussion and demand for this feature in #3085 - feel free to add your 👍 and share any insight if you know how to remove the backwards compatibility blocker.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Changes that touch dependencies, e.g. Dependabot, etc. documentation Improvements or additions to documentation size/M PR between 30-99 LOC
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Maintenance: test repo & packages with TypeScript 5.x
3 participants