Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using new on a function doesn't work unless merged with an interface. Why?

Tags:

typescript

This is all assuming noImplicityAny is set to true.

Given this:

function Bar() {
    this.f = 100;
}

this doesn't work:

let x = new Bar();

The error you get is:

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.

OK, I guess that kind of makes sense.

However, if I add an interface to the mix, it works fine:

interface Bar { 
     f: number;
}

function Bar() {
    this.f = 100;
}

let x = new Bar();
console.log(x.f);

When hovering over Bar you see this as the type:

interface Bar function Bar(): void

So I get that there's some merging going on. I'm just unclear as to why this works now? What exactly is this new merged type, and why is the return type of the Bar() function no longer implied to be any?

like image 918
BFree Avatar asked Jan 12 '17 22:01

BFree


1 Answers

What you're experiencing is Declaration Merging in TypeScript. Basically if two entities have same declared name, TypeScript merges them together into a single entity. This allows you to do some powerful things like writing declarations and interfaces for 3rd party JavaScript libraries to make them type aware.

In your first example, the compiler knows the return type of Bar(), which is void. It doesn't however know what constructor returns so new Bar() is assumed to be any.

But when you declare an interface of the same name, the compiler merges the interface Bar with function Bar(), and the interface now defines a shape which resembles the function, so the compiler picks it up as the type of new Bar(). Note that type of Bar() still stays void.

like image 126
Uzair Sajid Avatar answered Oct 19 '22 03:10

Uzair Sajid