Repository: TypeScript
Issue: ClassDecorator type is inconsistent with Decorators proposal, needs type parameters
Labels: Needs Investigation

# Bug Report

### 🔎 Search Terms

`classdecorator`
`decorator context`

### 🕗 Version & Regression Information

- This is the behavior in every version I tried (version 5.0+), and I reviewed the FAQ for entries about decorators.
- I was unable to test this on prior versions because proper ECMAScript decorators only became available in TypeScript 5.0.

### ⏯ Playground Link

<!--
  A link to a TypeScript Playground "Share" link which shows this behavior

  The TypeScript Workbench can be used for more complex setups, try
  https://www.typescriptlang.org/dev/bug-workbench/

  As a last resort, you can link to a repo, but these will be slower for us to investigate.
-->
[Playground Link](https://www.typescriptlang.org/play?target=99&jsx=0&ts=5.1.0-dev.20230415#code/MYGwhgzhAEBCkFMDC4rQN4CgC+nPAHsA7CAF2gDUCBLAExUggBEFCAnMUgt6AXmgBmAVyLBS1YgApM0WdABGiBlABc0UgE8ADggIC4S1BAA0MuYSKkEAD1JrlzVt07ckxK7dMBKaGs069AwhkI0wsOWgANxpaSQsPUi8AbjNZNgRSITYiBUNGFNxMAAEqOgcWdhc2fCNoAFVLbQRaCucrWmgbKyJaGHhghww8QosyaAAVJtpS+iNWji42ezmnBe4+Shjy1aqU4smdaa2VysWaxgmp+c5mztsEHr68tCxcIA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
class BaseClass {
}

const VoidClassDecorator = function(
    baseClass: typeof BaseClass,
    context: ClassDecoratorContext,
) : typeof BaseClass
{
    void(context);
    return baseClass;
}

@VoidClassDecorator
class UntypedDecorated extends BaseClass {

}

const TypedVoidClassDecorator: ClassDecorator = VoidClassDecorator;

@TypedVoidClassDecorator
class TypedDecorated extends BaseClass {
}
```

### 🙁 Actual behavior

Two errors:

```
Type '(baseClass: typeof BaseClass, context: ClassDecoratorContext<abstract new (...args: any) => any>) => typeof BaseClass' is not assignable to type 'ClassDecorator'.
  Target signature provides too few arguments. Expected 2 or more, but got 1.

Unable to resolve signature of class decorator when called as an expression.
  The runtime will invoke the decorator with 2 arguments, but the decorator expects 1.
```

The only difference between `TypedVoidClassDecorator` and `VoidClassDecorator` is the application of the ClassDecorator type, which doesn't take the context argument current ECMAScript decorators may use.

### 🙂 Expected behavior

No errors.

I would suggest a type taking three type parameters: the base class, a boolean flag for returning the original class type or returning void, and an arguments type which changes the return result.

```typescript
import { Class } from "type-fest";

/* eslint-disable @typescript-eslint/no-explicit-any */
export type ClassDecoratorFunction<
  BaseClassType extends Class<unknown>,
  ReturnsModified extends boolean,
  Arguments extends any[] | false
> = 
    Arguments extends any[] ? 
    (...args: Arguments) => ClassDecoratorFunction<BaseClassType, ReturnsModified, false> :
    (
        baseClass: BaseClassType,
        context: ClassDecoratorContext,
    ) => (ReturnsModified extends true ? BaseClassType : void);
```

[Playground Link, with fixes for earlier bugs](https://www.typescriptlang.org/play?target=99&jsx=0&ts=5.1.0-dev.20230415#code/JYWwDg9gTgLgBAbzgYQDYEMDOm4F84BmUEIcARDAJ5gCmAtATZjGQNwBQ7A9AFRxOpgAOxh0AJsEzoARqhpwAAlVqYAxlGBhRA4TC5CIdGgA8wg1cFHohlODy7sTkWHGXy0WTABEaq6OhhoADEAVyFVGGAIIQAedjg4ACEsGg9sABVqeRMYGiExHDTMGLCAawMAdyEAPgAaeLgAJRoYEKghTABZCAkCYBoxfmNc-JxpCAg5a3qEgEEoAHMQkDyYHBy8grhrSgBtAF04AB9CdFRMGnZquABeOAa5xeXV9eHNnB2DuAB+e4SEgAUADoQehFpgAFxweZLFYiTAASlu1yKPj8UACwTCESisWSFyKmVotSaLTaHW6vX6YhJBDOF2uEIecABzP+cGkKSKUPxqQwGSyM3Z-z8IhyUNRvn8gSgyGiuWGQoSSJu1wBzVa7S6PWAfQGQxGWxgUBC8l+vMJWTgUIAbhBgGIERx2Kp+TgLW7EMyoDR0GJoqhbJyLrdyGdUHBKBA2mx2LhOKLmHAAMohaSuzxo6XQUMEbGRaKs9nBvmeKFuCAEJJct1KuCihUwCVurMYmVysWK9hI8tZSvVglu9gIZl2h0Ahs5J3esnteuejajDk1zxe9m4Djx9gKVPpltStvQF2egCqIiyYlbAX1i62HtXI63ifgRIGu4z2CvMubmYPmKgoThAWsQVlW97YCSxqmrS9I0Ncdzvvu6L-s6CivmIiG-shMrHqu6FfjebxLuBOCPgm0RJgAavaYiSthOZ3HmQG4kW-wltyrh9mBK4Qcyk7DD+n5-u28o5PUPZwGOYjDqONEAuxbrTuyUkTqJwzTluCjUQ6dHZlAuHYHAZ5uGI2mXsJhGGu6PGkZwT4US+F5mbph5QIJ3jCVizHRDEoEDqWEGnOcNAwcF8FwM5SF6RwaFOTRLn-gZODoWZBGDLe1mDp4MlbkxOLRNCTxwmsADqlgABZftAAJmOglA0FAADyQi8lCzAaEICxIiO7I+pqQiEPmuIsmybE2b2tD9iRdbsvxTYoFFrkdo2dZIsyPXCgkKlzUpm1wH15LzquGXLllhkbXt-w+n6Aa2LV9VNS1KShvdDXNbyHCXfG65xpwCgws88JlTAlWeVAAJkCV5UQGQCJJUZ560GIAPFWlBrvP5RRer9LoOXA6Eoy8wOg-RbkLVhemAflIFcZjtZBRcJK7O1wgLPs4WE0DFVVVAMUE0VRPc2DENQwEsPw+hxOc2sWMnSR2PxkAA)

Update:  fixing the above playground code!

This might require deprecating ye olde `ClassDecorator` type.