1

similar to declare-class-type-with-typescript-pass-class-as-parameter but not work in this case

class Super {
  static hello(): void;
}

class SubA extends Super {
    // edited
    constructor(arg: string) { super(); } 
}

class SubB extends Super {
    // edited
    constructor(arg: string) { super(); }
}

function saySomething(cls: typeof Super) {
    cls.hello()
}

// turn out
// Argument of type 'typeof SubA' is not assignable to parameter of type 'typeof Super'.
// with vscode
saySomething(SubA)

saySomething(SubB)

I wanna to pass sub class of sequlize.Model as a parameter exactly

hwen
  • 13
  • 4
  • Hi and welcome to StackOverflow. I have written a minimal reproducible example in my answer but you should do it in your question. Your code works as is, the problem is actually related to the constructor functions and it doesn't appear in your question. – Guerric P Jan 04 '22 at 22:50
  • 1
    I write the pseudo-code from my original code without testing, sorry for that and I'll be more rigorous next time I ask a question. I just edited the example in description, hope the next one that visit this question won't be confused. Thanks for your kindly help @GuerricP – hwen Jan 05 '22 at 05:07
  • You're welcome. Thanks for taking my observation in account – Guerric P Jan 05 '22 at 08:09

1 Answers1

0

Here is a minimal reproducible example of your problem:

class Super {
  static hello(): void {
    console.log('hello');
  }
}

class SubA extends Super {
  constructor(arg: string) { super(); }
}

class SubB extends Super {
  constructor(arg: string) { super(); }
}

function saySomething(cls: typeof Super) {
  cls.hello()
}

// turn out
// Argument of type 'typeof SubA' is not assignable to parameter of type 'typeof Super'.
// with vscode
saySomething(SubA);

saySomething(SubB);

TypeScript playground

The problem occurs because a constructor function of an extending class doesn't necessarily take the same arguments, so it's not assignable to the Super class constructor.

As you don't need the constructor function at all but only the static properties (attached to the constructor), you could use a NoConstructor helper type in order to keep only the keys and remove the constructor function from the typeof Super type:

class Super {
  static hello(): void {
    console.log('hello');
  }
}

class SubA extends Super {
  constructor(arg: string) { super(); }
}

class SubB extends Super {
  constructor(arg: string) { super(); }
}

type NoConstructor<T> = Pick<T, keyof T>;

function saySomething(cls: NoConstructor<typeof Super>) {
  cls.hello(); // Works
}

saySomething(SubA); // Works

saySomething(SubB); // Works

TypeScript playground

Guerric P
  • 30,447
  • 6
  • 48
  • 86