Home > Net >  Using generics for classes with and without an array: Type 'string' does not satisfy the c
Using generics for classes with and without an array: Type 'string' does not satisfy the c

Time:09-19

I have a simple interface:

interface Animal<T> {
  isMatch: (value: T) => boolean
}

with these implementations:

class Dog implements Animal<string> {
  isMatch(input: string): boolean {
    // do something with string
  }
}

and

class Cat<T extends T[]> implements Animal<T> {
  isMatch(input: T[]): boolean {
    // do something with list
  }
}

I can instantiate a Dog without issue with:

const dog = new Dog("pug")

However, I can't instantiate a Cat with any of:

const siamese = new Cat<string>(...) // Type 'string' does not satisfy the constraint 'string[]'

const persian = new Cat<string[]>(...) // Type 'string[]' does not satisfy the constraint 'string[][]'

const sphynx = new Cat(["birman"]) // Type 'string' does not satisfy the constraint 'string[]'

I've used the generics / extends based on examples I've seen online, so not sure what I'm misunderstanding here.

CodePudding user response:

I understand why you used T extends T[], because of this error when you don't:

Type 'T' is not assignable to type 'T[]'.(2416)

input.tsx(11, 11): This type parameter might need an extends T[] constraint.

This error is misleading in this case, but if we think through what we want, we can get the solution.

You want isMatch to take the type T[]. However, Cat only takes T. Remember that isMatch is defined by the interface Animal, and in the interface, it takes T (in the interface). If we want these types to match, we just have to make Animal take T[]!

class Cat<T> implements Animal<T[]> {

And that's it.

Playground

  • Related