question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ConstructorParameters is not working for private constructors (and protected constructors)

See original GitHub issue

TypeScript Version: 3.4 Search Terms: ConstructorParameters, private constructor

Code

class Foo
{ public constructor(a: number, b: boolean, c: string) { } }

class Bar
{ private constructor(a: number, b: boolean, c: string) { } }

type FooCtorArgs = ConstructorParameters<typeof Foo>;
type BarCtorArgs = ConstructorParameters<typeof Bar>;

Expected behavior: BarCtorArgs is [number, boolean, string].

Actual behavior: Error in line 8: Type 'typeof Bar' does not satisfy the constraint 'new (...args: any) => any'. Cannot assign a 'private' constructor type to a 'public' constructor type.

Playground Link: https://www.typescriptlang.org/play/#src=class Foo { public constructor(a%3A number%2C b%3A boolean%2C c%3A string) { } } class Bar { private constructor(a%3A number%2C b%3A boolean%2C c%3A string) { } } type FooCtorArgs %3D ConstructorParameters<typeof Foo>%3B type BarCtorArgs %3D ConstructorParameters<typeof Bar>%3B


Use Case

Convenient factory pattern to mimic asynchronous object construction.

class Component
{
    public static async create(...args: ConstructorParameters<typeof Component>)
    {
        const component = new Component(...args);
        await component.initialize();
        return component;
    }

    private constructor(a: number, b: boolean, c: string)
    { /* stuff */ }

    private async initialize()
    { /* asynchronous setup */ }
}

Ideas for Solution

Allow visibility modifiers in interfaces. Yes, if you use an interface to outline the visible properties of an object to a user this makes no sense, but why not allow interfaces to be a flexible tool to specify internal rules of implementations? I think this problem could be solved, if the ConstructorParameters type could be defined like the following:

type ConstructorParameters<T extends {private new (...args: any[]): any}> = T extends new (...args: infer P) => any ? P : never;

Which is of course no allowed at the moment.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:34
  • Comments:11

github_iconTop GitHub Comments

3reactions
dhmk083commented, Aug 11, 2021

With some hacks this works and is quite short:

// 1. Make an abstract class
abstract class Foo {
    // 2. Make a public ctor
    constructor(readonly x: number, protected y: string) {}

    public static create = createFactory(Foo)
}

function createFactory<T extends abstract new (...args: any) => any>(c: T) {
  return (...args: ConstructorParameters<T>): InstanceType<T> => {
    // @ts-ignore
    return new c(...args)
  }
}
1reaction
Slioncommented, Apr 22, 2022

But you can declare derived class as abstract too, can’t you? 😃

abstract class Foo {...}

abstract class Bar extends Foo {...}

new Bar(1, 'a') // expected error
Bar.create(1, 'a') // ok

You are correct, that works great!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Java: accessing private constructor with type parameters
Something like this should work. Constructor<Foo> constructor= (Constructor<Foo>) Foo.class.getDeclaredConstructors()[0]; constructor.
Read more >
Entity types with constructors - EF Core - Microsoft Learn
The constructor parameters can be bound to mapped properties, or to various kinds of services to facilitate behaviors like lazy-loading.
Read more >
@NoArgsConstructor, @RequiredArgsConstructor ...
Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field....
Read more >
Kotlin Constructors | Baeldung on Kotlin
A guide to defining and using constructors in Kotlin. ... like @Autowired or access modifiers, like private or protected.
Read more >
PHP 8: Constructor property promotion - Stitcher.io
... ditch all the class properties and the variable assignments, and prefix the constructor parameters with public , protected or private .
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found