TypeScript: Merged declaration of construct signature does not work for function

Bug Report

🔎 Search Terms

typescript declaration merging function

Please see Declaration Merging

🕗 Version & Regression Information

$ yarn tsc --version
Version 4.6.3
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about declaration merging

⏯ Playground Link

Playground link with relevant code

💻 Code

// Function class example
interface MyFunctionClass {
    new(): MyFunctionClass; // let's assume here it has a constructor
    myMethod(): void;
}

function MyFunctionClass(this: MyFunctionClass) {
    this.myMethod = Number;
}

const myClassInstance = new MyFunctionClass();
// 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type

🙁 Actual behavior

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

🙂 Expected behavior

Since declaration merging should work because it’s not the case in Disallowed Merges section. I should be able successfully create my function class

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (7 by maintainers)

Most upvoted comments

Interface declares a type. Function declares a value. There’s no overlap.

A class declares both a value and a type.

Your example is the same as:

interface A { /* ... */ }

const A = 'foo';

Why should this merge? It shouldn’t.

I can assure you I’ve been looking, and there is no bug here. Functions do not bring an interface name into scope; that’s not a bug, it’s how TS is designed. If you want to see something different that would be a feature request.

It feels like you’re conflating the static side and instance side of a class. class Foo {} beings an interface named Foo into scope corresponding to the instances of the class, and it also beings a namespace named Foo into scope corresponding to the static side of the class. These have the same name but are different kinds of thing. A function statement function Bar() {} has a namespace Bar associated with it (which allows for expando properties like Bar.baz = 123) but no interface. Maybe you want to ask for the ability to merge a construct signature into a namespace, but that’s not how you’re phrasing it. And even if you rephrase it, it’s a feature request, not a bug. Everything here is working as intended.

But… I’m not a TS team member, just a nosy bystander. So I’ll remove myself from the discussion and wait for the TS team to respond as they see fit. Good luck!