Skip to content

Allow value pointing to a class or whose type has a new signature to be used as a typeΒ #45013

Closed
@JoshuaKGoldberg

Description

@JoshuaKGoldberg

Suggestion

πŸ” Search Terms

refers to value used as type static class generic

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

When a class is created by a static method, there doesn't seem to be a way to directly use it as a class type.

πŸ“ƒ Motivating Example

class BaseClass {
    constructor() {}

    static cloneClass() {
        return class extends this { };
    }
}

function takeBase(base: BaseClass) {} // Ok
takeBase(new BaseClass()); // Ok

const CreatedClass = BaseClass.cloneClass();

function takeCreated(created: CreatedClass) {}
//                            ~~~~~~~~~~~~
// 'CreatedClass' refers to a value, but is being used as a type here.
// Did you mean 'typeof CreatedClass'?

takeCreated(new CreatedClass()); // Ok

While CreatedClass is indeed a value, it's a value that happens to be equal to a class.

πŸ’» Use Cases

In general, class factories like this are rather unwieldy to set up in the type system.

For a specific use case, see gr2m/javascript-plugin-architecture-with-typescript-definitions#57, as posted in SO at https://stackoverflow.com/questions/68201386/how-to-make-required-constructor-options-optional-when-they-were-set-using-mycla. Those Oktokit classes have a static defaults member that returns a new class. That new class has a constructor parameter whose type information must be informed by the previous static class' generic.

See this playground link for a version that uses an interface to describe the class, and this playground link for a verson that purely uses a static class. The former would be resolved nicely by this issue's requested feature; the latter would be doable in a more complex way if #26242 and/or #5863 are implemented.

cc @gr2m

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions