0

I have following code:

class Factory<K, T extends new (...p: any) => any> {
    add(key: K, fn: (...p: ConstructorParameters<T>) => InstanceType<T>) {
    }
}

class Foo {
    constructor(a: number) {
    }
}

class Boo {
    constructor(a: number) {
    }
}

new Factory<number, typeof Foo>().add(1, (a) => new Boo(a))

I would assume that this should fail to compile as Boo is not derived from Foo. But it works fine.

Am I missing something?

Playground

pankleks
  • 693
  • 6
  • 14
  • 3
    TypeScript is a structurally typed language, if two objects have the same shape, they are considered to be of the same type. If you add something to `Foo` that `Boo` doesn't have, it'll stop compiling. – Nadia Chibrikova May 25 '21 at 14:04
  • @NadiaChibrikova is correct. Here's the official explanation: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-oop.html#rethinking-types. but if you *need* nominal types, there are some tricks: https://basarat.gitbook.io/typescript/main-1/nominaltyping, https://michalzalecki.com/nominal-typing-in-typescript/, https://betterprogramming.pub/nominal-typescript-eee36e9432d2 – Inigo May 25 '21 at 20:06
  • Also, there is talk about introducing some kind of native support for nominal types: https://github.com/microsoft/TypeScript/issues/202 and https://github.com/microsoft/TypeScript/pull/33038 – Inigo May 25 '21 at 20:07
  • Also related: https://stackoverflow.com/a/55281684/11407695 – Oleg Valter is with Ukraine May 26 '21 at 08:45
  • 1
    It's helpful to read `extends` as "is assignable to", so your generic type parameter just needs to "be assignable to" `typeof Foo`, which `Boo` is (thanks to structural typing, as @NadiaChibrikova said). – superhawk610 May 26 '21 at 08:49

0 Answers0