Repository: TypeScript
Issue: Experimental decorators do not get access to the initial value when using auto-accessors
Labels: Needs Investigation

### 🔎 Search Terms

In order to give a good out-of-the-box experience with our library that vends decorators, we are trying to make a single set of decorators that works under the following configurations:

1. Experimental decorators on class fields (with `useDefineForClassFields: false`)
2. Standard decorators on auto-accessors
3. Experimental decorators on auto-accessors

Case (3) may seem unusual at first, but it's very important for incremental migration from experimental decorators to standard decorators. The goal is to enable experimental decorators to be _callsite_ compatible with standard decorators so that callsites and files can be upgraded one-at-a-time without changing the tsconfig, and after the callsites are updated `experimentalDecorators` can be turned off.

This mostly works except that in case (3) the decorators cannot get access to the initial field value because it's set directly to the auto-accessor backing store and skips the setter. In case (1) the initial value goes through the setter, in case (2) it goes through the `init()` callback, but in case (3) we can't see it at all.

Case (3) is actually important for multiple reasons:
- Incremental migration as mentioned
- It enables one version of decorator docs (aside from talking about configs) and decorator-using code samples through our docs and example repositories.
- It enables projects to start with or migrate to standard decorators and change back to experimental decorators in case the size penalty of standard decorators is too much (we're seeing a ~50% code size penalty on porting a library to standard decorators above the size with experimental decorators) by just changing the tsconfig.



### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about decorators


### ⏯ Playground Link

https://www.typescriptlang.org/play?experimentalDecorators=true&target=9#code/MYewdgzgLgBFCm0YF4YAoBQMYAcBOIUIA8ngCKLB4CWOReAXDMQEYBW8wUANFjGAEMAtvCYAFAjnh4oATwDS8Wb2wATSjTohGMCSCkzZFCFVr0MASiYCwslAD4YAbz554UAK54wzvtgDm7mgWvthhMKCQIAA28AB00SD+aADkgVApFgDcfmFunt4w6iaa9HHpAIRxwALR0WhQABbUENm5AL4qYRBBAG5MHmAA1mAgAO5gIS7h2JEQMfGJySk9GdwwvW0zRRpm2nGrVTV1Dc0Q65s54e18NzcYwNECEBAwAIKhMAACCEgCwMBEPM8DAAGYgEAoGApFgCPApHL3AD0SJgAFEAB5SLjwVQRcDzWJMABEq2J62JsLwxIeBNgAihYHgY3ewRyGBRMCWEBJZIpsIAXjSBHFwZDUDCBAKERggA

### 💻 Code

```ts
const test = (
  protoOrDescriptor: Object,
  name: PropertyKey,
  descriptor: PropertyDescriptor
): any => {
  return {
    get() {
      console.log('get');
      return descriptor.get!.call(this);
    },
    set(v: unknown) {
      console.log('set', v);
      descriptor.set!.call(this, v);
    }
  }
}

class A {
  @test accessor foo = 'bar';
}

// Expected console: "set", "bar"
const a = new A();

// logs: "set", "baz"
a.foo = 'baz';

```


### 🙁 Actual behavior

The setter isn't called, since the output initializes the private storage directly:

```ts
class A {
    #foo_accessor_storage = 'bar';
    get foo() { return this.#foo_accessor_storage; }
    set foo(value) { this.#foo_accessor_storage = value; }
}
```

### 🙂 Expected behavior

The setter is called. Initializers for decorated accessors under experimental decorators are called as statements in the constructor:

```ts
class A {
    #foo_accessor_storage;
    get foo() { return this.#foo_accessor_storage; }
    set foo(value) { this.#foo_accessor_storage = value; }
    constructor() {
      this.foo = 'bar';
    }
}
```

### Additional information about the issue

_No response_