Skip to content

Returned type of class decorator is ignored when class is decorated #54663

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

Closed
b-strauss opened this issue Jun 15, 2023 · 2 comments
Closed

Returned type of class decorator is ignored when class is decorated #54663

b-strauss opened this issue Jun 15, 2023 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@b-strauss
Copy link

Bug Report

Using decorators and proxies it's now possible to elegantly create classes which don't require the new keyword for instantiation. Unfortunately TypeScript doesn't allow this.

🔎 Search Terms

decorators, class decorators

🕗 Version & Regression Information

  • Tested in 'Nightly' version

⏯ Playground Link

Playground link with relevant code

💻 Code

type Callable<T extends new (...args: any) => any> = T & ((...args: ConstructorParameters<T>) => InstanceType<T>);

function makeCallable<C extends new (...args: any) => any> (clazz: C): Callable<C> {
  return new Proxy(clazz, {
    apply (target, thisArg, argArray) {
      return new target(...argArray);
    },
  }) as unknown as Callable<C>;
}

function callable<C extends new (...args: any) => any> (clazz: C, context: ClassDecoratorContext<C>): Callable<C> {
  return makeCallable(clazz);
}

// Using function
const User = makeCallable(class {
  constructor (name: string, age?: number) {}
});

const x = new User('foo');
console.log(x instanceof User);

const y = User('bar'); // works
console.log(y instanceof User);

// Using decorator
@callable
class DecoratedUser {
  constructor (name: string, age?: number) {}
}

const a = new DecoratedUser('foo', 19);
console.log(a instanceof DecoratedUser);

const b = DecoratedUser('bar', 12); // Value of type 'typeof DecoratedUser' is not callable.
console.log(b instanceof DecoratedUser);

🙁 Actual behavior

TypeScript does not allow for the proxied class to be called, although this is valid js code and all instanceof checks are passing.

🙂 Expected behavior

TypeScript should use the return type of the decorator as the new type for the class.

@jcalz
Copy link
Contributor

jcalz commented Jun 16, 2023

This is probably less "bug" and more "missing feature". Cross-linking to #51347

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 22, 2023
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants