Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use 'new' error on intersection type with constructor #17388

Closed
unional opened this issue Jul 25, 2017 · 5 comments
Closed

Cannot use 'new' error on intersection type with constructor #17388

unional opened this issue Jul 25, 2017 · 5 comments
Labels
Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@unional
Copy link
Contributor

unional commented Jul 25, 2017

tsc: 2.4.2

class X { }
declare interface ConstructorAnyArgs<TClass> {
    new (...args: any[]): TClass
}


function foo(): ConstructorAnyArgs<X> { return }
function boo(): ConstructorAnyArgs<X> & { superclass: any } { return }

let Y = foo()
let y = new Y()

let Z = boo()
let z = new Z() // Cannot use 'new' with an expression whose type lacks a call or construct signature.

http://www.typescriptlang.org/play/index.html#src=class%20X%20%7B%20%7D%0D%0Adeclare%20interface%20ConstructorAnyArgs%3CTClass%3E%20%7B%0D%0A%20%20%20%20new%20(...args%3A%20any%5B%5D)%3A%20TClass%0D%0A%7D%0D%0A%0D%0A%0D%0Afunction%20foo()%3A%20ConstructorAnyArgs%3CX%3E%20%7B%20return%20%7D%0D%0Afunction%20boo()%3A%20ConstructorAnyArgs%3CX%3E%20%26%20%7B%20superclass%3A%20any%20%7D%20%7B%20return%20%7D%0D%0A%0D%0Alet%20Y%20%3D%20foo()%0D%0Alet%20y%20%3D%20new%20Y()%0D%0A%0D%0Alet%20Z%20%3D%20boo()%0D%0Alet%20z%20%3D%20new%20Z()%20%2F%2F%20Cannot%20use%20'new'%20with%20an%20expression%20whose%20type%20lacks%20a%20call%20or%20construct%20signature.%0D%0A

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jul 25, 2017
@RyanCavanaugh
Copy link
Member

This regressed between 2.1 and 2.2

@mhegazy mhegazy added this to the TypeScript 2.7 milestone Nov 9, 2017
@mhegazy mhegazy modified the milestones: TypeScript 2.7, TypeScript 2.8 Jan 9, 2018
@mhegazy mhegazy modified the milestones: TypeScript 2.8, TypeScript 2.9 Mar 9, 2018
@MrMatthewLayton
Copy link

@mhegazy @RyanCavanaugh

Adding this from StackOverflow for completeness

I have identified a problem when using intersection types in TypeScript...

I have three type aliases:

  • Prototype<T> - expresses an object/class that has a prototype property.
  • DefaultCtor<T> - expresses an object/class with a default constructor.
  • ParameterizedCtor<T> expresses an object/class with a parameterized constructor.

I have tried these intersection permutations:

  • Prototype<T> & DefaultCtor<T> - works fine.
  • Prototype<T> & ParameterizedCtor<T> - raises a compiler error.

Example

type Prototype<T> = {
    prototype: T;
}

type DefaultCtor<T> = {
    new(): T;
}

type ParameterizedCtor<T> = {
    new(...args: any[]): T
}

function makeDefault<T>(ctor: Prototype<T> & DefaultCtor<T>): T {
    return new ctor();
}

function makeWithArgs<T>(ctor: Prototype<T> & ParameterizedCtor<T>, ...args: any[]): T {
    return new ctor(...args);
    // ERROR: Cannot use 'new' with an expression whose type lacks a call or construct signature.
}

Try it in the Playground

Error
The error occurs with the Prototype<T> & ParameterizedCtor<T> intersection:

Cannot use 'new' with an expression whose type lacks a call or
construct signature.

Why does the TypeScript compiler recognise the Prototype<T> & DefaultCtor<T> intersection type as having a constructor, but not the Prototype<T> & ParameterizedCtor<T> intersection type?

@mhegazy mhegazy assigned weswigham and unassigned sandersn Apr 26, 2018
@gssjr
Copy link

gssjr commented Jun 15, 2018

I may be running into this as well. Here's my example:

declare namespace __example {
  interface A {
    aProp;
  }

  interface AConstructor {
    new(): A;
  }

  export const A: AConstructor;
}

class MyClass {
  myInvalidFunc = (A: __example.A) => {
    // [ts] Cannot use 'new' with an expression whose type lacks a call or construct signature.
    const a: __example.A = new A();
  }

  myValidFunc = (A: __example.AConstructor) => {
    const a: __example.A = new A();
  }
}

@weswigham
Copy link
Member

myInvalidFunc = (A: __example.A) => {
// [ts] Cannot use 'new' with an expression whose type lacks a call or construct signature.
const a: __example.A = new A();
}

This is correct. __example.A isn't a constructor.

@mattmccutchen
Copy link
Contributor

A silly mistake in the logic for handling mixin classes. Fix is in #27701.

mattmccutchen added a commit to mattmccutchen/TypeScript that referenced this issue Feb 9, 2019
intersection also contains non-constructor types.

Fixes microsoft#17388.
@RyanCavanaugh RyanCavanaugh removed this from the Community milestone Mar 7, 2019
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Mar 7, 2019
weswigham pushed a commit that referenced this issue Mar 12, 2019
…he (#27701)

intersection also contains non-constructor types.

Fixes #17388.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

8 participants