1

Here is a minimal example of my problem

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];

It throw this 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'

I would like to have an array of Speaker that accepts any type of Living.

Thanks for your time!

1 Answer 1

2

With the way you've defined things, Speaker<Living> means an object with a speak function that takes in a Person | Dog as its argument. When you create michel, you have the following function, which works fine if given a Person:

(person) => console.log(`I have ${person.arms} arms`)

But it would not work if given a Person | Dog, because it's trying to access the .arms property of a dog. That mismatch and others is why typescript is telling you that Speaker<Person> cannot be assigned to Speaker<Living>

If you want the array to be a mix of objects, some of which take Persons for their speak function, some of which take Dogs, then the type for that will be:

const speakers: Array<Speaker<Person> | Speaker<Dog>> = [michel];

EDIT: if your Living union is large, or you want speakers to update automatically when more types are added into Living, then you can use the following to get typescript to generate the Speaker<Person> | Speaker<Dog> union for you:

type Distribute<T> = T extends Living ? Speaker<T> : never;

const speakers: Array<Distribute<Living>> = [michel];
// speakers is of type Array<Speaker<Person> | Speaker<Dog>>

Playground link

Sign up to request clarification or add additional context in comments.

2 Comments

Okay I got it. Is there a way of specifying all the Living instead of putting multiple |? For example if I add a new type to the Living I would like this array to be automatically retyped.
Added in an example of how to do that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.