1

I am trying to type a method, where I pass a class and a factory as an argument. Both should strongly point to type T, but the compiler is okay with the following simplified test. Is there a stronger approach to type a class reference?

type Class<T> = new (...args: any[]) => T
class A { }
class B { }
const test = <T>(type: Class<T>, factory: () => T) => { }
test(A, () => new B()) // why is this accepted?

I tried all answers from Is there a type for "Class" in Typescript? And does "any" include it?

1 Answers1

2

TypeScript is structurally typed, commonly called duck typing.

Notice that if I make the classes themselves structurally different, you get the expected behavior:

class A { foo = "" }
class B { bar = 0 }

Playground

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • Interesting, but wouldn't this imply that one difference is enough? [Playground](https://www.typescriptlang.org/play?jsx=0#code/C4TwDgpgBAwgNgQwM5IDwBUB8UC8UB2EA7lABQB0lCATgOZIBcUC+IA2gLoCUu26AsACgAxohRQAglADeUKAF8ho5EigAhGVABGNXFAAMCpQHt8SYFGARzejJlKhITeCrsAaKADMEw4MeogTKQ8OHwh2LKKglbmpBIewbwExOrBPAD06VBEABYgUACWqsA5RczCwhBgVgAmAPxCQA) – andré michelle Sep 08 '22 at 16:42
  • 1
    @AndMic No, because you are expecting A, and B is assignable to A. This is true because A does not have anything, while B has one property. If you don't expect anything to come with something, do you really care? – kelsny Sep 08 '22 at 17:00
  • 1
    Here's the TypeScript docs about type compatibility: https://www.typescriptlang.org/docs/handbook/type-compatibility.html – kelsny Sep 08 '22 at 17:03
  • I do care while developing a strongly typed api under laboratory conditions in the beginning (empty mook classes, interfaces, etc.). This is very confusing and I admittedly fail to see the advantages of this typing behaviour just yet, but I appreciate your explanations. Thanks! – andré michelle Sep 09 '22 at 05:14