Aquí hay un ejemplo mínimo de mi problema.
interface Dog { legs: number; } interface Person { arms: number; } type Living = Person | Dog; interface Speaker<T extends Living> { speak: (living: T) => void; }; const michel: Speaker<Person> = { speak: (person) => console.log(`I have ${person.arms} arms`) }; const speakers: Array<Speaker<Living>> = [michel];Lanza este error
Type 'Speaker<Person>' is not assignable to type 'Speaker<Living>'. Type 'Living' is not assignable to type 'Person'. Property 'harms' is missing in type 'Dog' but required in type 'Person' Me gustaría tener una serie de Speaker que acepten cualquier tipo de Living .
¡Gracias por tu tiempo!
Con la forma en que ha definido las cosas, Speaker<Living> significa un objeto con una función de hablar que toma una Person | Dog como argumento. Cuando crea michel , tiene la siguiente función, que funciona bien si se le asigna una Person :
(person) => console.log(`I have ${person.arms} arms`) Pero no funcionaría si se le diera una Person | Dog , porque está intentando acceder a la propiedad .arms de un perro. Esa discrepancia y otras son las razones por las que el mecanografiado le dice que Speaker<Person> no se puede asignar a Speaker<Living>
Si desea que la matriz sea una combinación de objetos, algunos de los cuales toman Person s para su función de habla, algunos de los cuales toman Dog s, entonces el tipo para eso será:
const speakers: Array<Speaker<Person> | Speaker<Dog>> = [michel]; EDITAR: si su unión de Living es grande, o si desea que los altavoces se actualicen automáticamente cuando se agreguen más tipos a Living , puede usar lo siguiente para obtener mecanografiado para generar el Speaker<Person> | Speaker<Dog> Unión de Speaker<Person> | Speaker<Dog> para usted:
type Distribute<T> = T extends Living ? Speaker<T> : never; const speakers: Array<Distribute<Living>> = [michel]; // speakers is of type Array<Speaker<Person> | Speaker<Dog>>