Skip to content

Conversation

@gibson042
Copy link

Fixes #43450

Assignment to this.constructor fails when this inherits from an object with a non-configurable non-writable constructor property (the so-called "override mistake"): TypeScript Playground.

This PR updates extendsHelper to use Object.defineProperty when available, which is immune to the override mistake (and incidentally also creates a non-enumerable constructor property as required by the specification).

Copilot AI review requested due to automatic review settings September 4, 2025 21:05
@github-project-automation github-project-automation bot moved this to Not started in PR Backlog Sep 4, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR updates the TypeScript compiler's __extends helper function to support downleveling classes that extend frozen base classes. The change replaces direct property assignment to this.constructor with Object.defineProperty when available, which avoids the "override mistake" that occurs when the base class has a non-configurable, non-writable constructor property.

  • Updated the __extends helper to use Object.defineProperty for setting the constructor property when available
  • Added fallback to direct assignment for older environments that don't support Object.defineProperty
  • Ensures compliance with the ECMAScript specification by creating a non-enumerable constructor property

@jakebailey
Copy link
Member

I am not sure we need this at all; ES5 is being deprecated in 6.0 and will not be implemented in 7.0.

@gibson042
Copy link
Author

I am not sure we need this at all; ES5 is being deprecated in 6.0 and will not be implemented in 7.0.

In the meantime, this can fix some very real problems for the remainder of 5.x and the entirety of 6.x. Is there any reason to stick with the incorrect implementation?

@RyanCavanaugh
Copy link
Member

It's very common that people have dependencies on incorrect behavior and we're trying to minimize friction for people moving to 6.0. The user-side workarounds here are fairly straightforward (inject your own __extends or use a different downleveler).

Closing as the linked issue is not approved for PRs.

@github-project-automation github-project-automation bot moved this from Not started to Done in PR Backlog Sep 5, 2025
@gibson042
Copy link
Author

It's very common that people have dependencies on incorrect behavior and we're trying to minimize friction for people moving to 6.0.

Are you suggesting that people are depending upon an error being thrown when evaluating the definition of a class that uses extends?

The user-side workarounds here are fairly straightforward (inject your own __extends or use a different downleveler).

I don't consider those workarounds to be practical for something as common as extends, but they aren't even available when the problem manifests inside a dependency, which is what prompted me to open this PR (specifically, npm package json-rpc-2.0 dist/models.js line 53 uses the default __extends against Error, which fails when Error.prototype is frozen as demonstrated in the TypeScript Playground).

@naugtur
Copy link

naugtur commented Sep 17, 2025

TypeScript users publishing to npm registry are publishing the resulting code, so a user replacing the downleveler is not a workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

ES5 class rewriting incompatible with frozen intrinsics

4 participants