60

I encountered new() in the official document here about generics.

Here is the code context:

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

The above code is transpiled to the following JavaScript code:

function create(c) {
    return new c();
}

new() is illegal syntax in JavaScript. What does it mean in TypeScript?

Furthermore, what does {new(): T; } mean? I know it must be a type, but how?

Nicolas S.Xu
  • 13,794
  • 31
  • 84
  • 129
  • 1
    Possible duplicate of [How does typescript interfaces with construct signatures work?](http://stackoverflow.com/questions/13407036/how-does-typescript-interfaces-with-construct-signatures-work) – Fabian Lauer Sep 21 '16 at 17:28
  • used in an interface or inline interface it describes signature of the constructor. – toskv Sep 21 '16 at 17:39
  • @toskv new() looks like a function invocation. Why it is the signature of the constructor? – Nicolas S.Xu Sep 21 '16 at 17:44
  • in es5 the way you implement classes is by creating in instances of functions. that's just the way to do it new functionName(). – toskv Sep 21 '16 at 18:52

5 Answers5

78

new() describes a constructor signature in typescript. What that means is that it describes the shape of the constructor. For instance take {new(): T; }. You are right it is a type. It is the type of a class whose constructor takes in no arguments. Consider the following examples

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

What this means is that the function create takes an argument whose constructor takes no arguments and returns an instance of type T.

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

What this would mean is that the create function takes an argument whose constructor accepts one number a and returns an instance of type T. Another way to explain it can be, the type of the following class

class Test {
    constructor(a: number){

    }
}

would be {new(a: number): Test}

Nahush Farkande
  • 5,290
  • 3
  • 25
  • 35
  • 2
    maybe adding a class implementing them (and their transpilation to javascript) would help clear the problem. – toskv Sep 21 '16 at 18:28
  • After transpilation the `type` would have no existence since there is no concept of types in javascript and hence there would be no `new()`. There is no such thing as `new()` in javascript.. it is only in typescript – Nahush Farkande Sep 21 '16 at 19:13
  • 1
    ofcourse there is new functionName() in javascript. you create a new instance of that function object. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new – toskv Sep 21 '16 at 19:32
  • 2
    Yes but there is no `new()`, there is `new functionName()` and `new ClassName()` but no `new()` – Nahush Farkande Sep 21 '16 at 20:08
  • ah, that is right indeed. :) it's just typescript stuff – toskv Sep 21 '16 at 20:14
  • I can't get the example to work function create(c: {new(): T; }): T { return new c(); } and is copy paste.https://www.typescriptlang.org/docs/handbook/generics.html – titusfx Aug 04 '17 at 08:02
  • It seems to work fine. Check [here](https://www.typescriptlang.org/play/#src=function%20create%3CT%3E(c%3A%20%7B%20new%20()%3A%20T%3B%20%7D)%3A%20T%20%7B%20return%20new%20c()%3B%20%7D%0A%0Aconsole.log(create%3CObject%3E(Object))). If possible could you reproduce your problem on the typescript playground and share it here? – Nahush Farkande Aug 07 '17 at 07:03
  • Add something about `['new']():` and `new: () =>`. – Knu Dec 31 '18 at 08:25
  • Honestly, couldn't the folks at Typescript think of a more cryptic way of doing this? – Thiago Pereira Maia Oct 04 '21 at 01:07
  • So this would only work if the constructor of the class had no arguments? Can we generalize this for any class? – Alaska Nov 23 '22 at 21:24
15

The new keyword is used to create an instance of a class, so in its simplest form:

class SimpleClass {
}

Would be constructed as follows:

let simpleClassInstance = new SimpleClass();

This is all well and good, but how do you create an instance of a generic class, i.e.:

class SimpleClassFactory< T > {
    static create( T ) {
        return new T(); // compile error could not find symbol T
    }
}

Would be used as follows:

let simpleClassInstance = SimpleClassFactory.create(SimpleClass);

Here, we are attempting to use the class definition to create an instance of a class. This will generate a compile error.

So we need to refer to the type by its constructor signature:

class SimpleClassFactory< T > {
    static create( type: { new(): T ;} ) {
        return new type(); // succeeds
    }
}
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
blorkfish
  • 21,800
  • 4
  • 33
  • 24
2

What is new() => T?

Essentially it is a way to declare an "Object Type" in which you can then create an instance of said "Object Type" with.

Example

class MyClass {
  // ...
}

// Creates new object types that don't have arguments in their constructors
function createObjectGivenObjectType<T>(ObjectType: new() => T): T {
  return new ObjectType();
}

const myObject: MyClass = createObjectGivenObjectType(MyClass);

Simplify new() => T

I personally find it confusing when I see new() => T in a codebase. To simplify the problem, and to allow for better code readability, abstract this idea away from other devs by declaring a new type in your codebase called Type:

export type Type<T> = new (...args: any[]) => T;

Then the above createObjectGivenObjectType function can become:

// Then this reads as: ObjectType is a type of T
function createObjectGivenObjectType<T>(ObjectType: Type<T>): T {
  return new ObjectType();
}

Furthermore, what does { new(): T; } mean? I know it must be a type, but how?

From the example you give it appears to be a more obtuse way of passing in an "Object Type" to a function.

Some examples that all do the same thing:

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


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

function create<T>(c: Type<T>): T {
  return new c();
}
create(X);
Kevin Baker
  • 569
  • 5
  • 8
0

So in the documentation is mentions that the syntax is for "When creating factories in TypeScript using generics".

If you look at a larger example that they have:

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function findKeeper<A extends Animal, K> (a: {new(): A;
    prototype: {keeper: K}}): K {

    return a.prototype.keeper;
}

findKeeper(Lion).nametag;  // typechecks!

a: {new(): A
// is actually creating a new instance of the type A which is extending Animal.
// it is necessary to refer to class types by their constructor functions
inoabrian
  • 3,762
  • 1
  • 19
  • 27
0

{new(): T } actually is a class type that is referred to as a constructor function. another syntax of representing a type as a constructor function is by using this syntax

new () => Type

In the case of the create functions, an alias could be represented as

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

Constructor functions are generally helpful in typescript for creating class instances from factory functions. In the case of the factory function 'create' above, it accepts a class type whose constructor has no arguments "{new(): T; }" and returns an instance of the class "T".

Example:

class BeeKeeper {
  hasMask: boolean = true;
}
     
const newClass = create(BeeKeeper)

console.log(newClass instanceof BeeKeeper) // Prints true 

constructor functions can also be represented as below in the case of a constructor function that accepts arguments

new (b: string) => T
       or
{new(b: string): T }