4

What is the meaning of the type declaration for dialogComponent in the following Typescript code snippet?

createDialog(dialogComponent: { new(): DialogComponent }) :
    Promise<ComponentRef<DialogComponent>> { ... }

(From https://www.lucidchart.com/techblog/2016/07/19/building-angular-2-components-on-the-fly-a-dialog-box-example).

I found the following question that expands on answers received so far: How to create a new object from type parameter in generic class in typescript?

Tom Nurkkala
  • 622
  • 1
  • 6
  • 15
  • I guess it means that function `createDialog` has object argument that has method `new()`, nothing special. – Lyubimov Roman Aug 16 '16 at 03:37
  • It means that `dialogComponent` is of a type which has a constructor which takes no parameters and returns a `DialogComponent`. It's likely that the same could be accomplished by `createDialog(dialogComponent: typeof DialogComponent)`. –  Aug 16 '16 at 03:41
  • It looks like `{ new(): DialogComponent }` is supposed to be a type declaration for the dialogComponent parameter, but it doesn't make sense to use 'new()' as an object key. I'm not sure what it's supposed to do, but in the plunker demo ([link](https://plnkr.co/edit/GmOUPtXYpzaY81qJjbHp?p=preview)), I replaced the `new()` with random text. Everything still worked as before with no errors so apparently is doesn't actually do *anything*. – ABabin Aug 16 '16 at 03:55
  • Also in the demo, createDialog is called in the app component with the actual DialogComponent class itself passed as the parameter. It then uses an Angular 2 package, ComponentResolver, to, I think, dynamically create a DialogComponent. ComponentResolver has been deprecated so I'd advise against using this code unless you want to have to rewrite it in the future. You can make a pop-up dialog without dynamic component building fairly easily, if that's what you're looking to do. – ABabin Aug 16 '16 at 03:55
  • I think it is not related to `new Class()`. I mean the argument should be like this `{new: () => funcThatReturnsDialogComponent()}` – Lyubimov Roman Aug 16 '16 at 03:57
  • Thanks, Andrew; the reason I was looking at this code was to try to upgrade it to the latest ng2 API. – Tom Nurkkala Aug 16 '16 at 16:31
  • Does this answer your question? [what is new() in Typescript?](https://stackoverflow.com/questions/39622778/what-is-new-in-typescript) – Bergi Dec 13 '20 at 15:14

2 Answers2

4

When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. So instead of using type:T, use type: { new(): T;}.

function create<T>(c: {new(): T; }): T {
    return new c();
}

More details at here.

Ha Hoang
  • 1,644
  • 12
  • 14
3

In your example dialogComponent is the actual class and not an instance of it, or in other words it's the constructor function of the class.
Here's an example:

interface A {}

class A1 implements A {}
class A2 implements A {}

function factory(ctor: { new(): A }): A {
    return new ctor();
}

let a1 = factory(A1); // type of a1 is A
let a2 = factory(A2); // type of a2 is A

As you can see, the factory function expects an object which can be called using the new keyword, and such objects are the classes.

This is widely used in the lib.d.ts, for example the ArrayConstructor:

interface ArrayConstructor {
    new (arrayLength?: number): any[];
    new <T>(arrayLength: number): T[];
    new <T>(...items: T[]): T[];
    (arrayLength?: number): any[];
    <T>(arrayLength: number): T[];
    <T>(...items: T[]): T[];
    isArray(arg: any): arg is Array<any>;
    readonly prototype: Array<any>;
}
Nitzan Tomer
  • 155,636
  • 47
  • 315
  • 299