peter flanagan
peter flanagan

Reputation: 9790

React typescript is not assignable to parameter of type

I am using typescript in a react project.

I am getting the following error.

Argument of type '{ teams: { home: { name: string; }; away: { name: string; }; }[]' is not assignable to parameter of type 'Fixtures[] | (() => Fixture[])'.

My type definitions and use in a react component are below.

type Team = {
    name: 'Liverpool' | 'Man Utd';
};

type Fixtures = {
    teams: {
        home: {
            name: Team;
        },
        away: {
            name: Team;
        },
        winner: Team;
    };
};

const initialFixtures = [
    {
        teams: {
            home: {
                name: 'Liverpool',
            },
            away: {
                name: 'Man Utd',
            },
        },
        winner: 'Liverpool',
    },
];

I am then using this in my React component like below but

// Error is in `initial fixtures`
const [fixtures, updateFixtures] = useState<Fixtures[]>(initialFixtures);

Can anyone see what I am doing wrong? I can't see where it is inferring it to be a string when I have said it is a Team.

Upvotes: 0

Views: 1464

Answers (3)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249506

The problem is not related to react, its related to how Typescript infers string literal types. Typescript will not infer string literal types unless it has a reason to do so.

In this case initialFixtures is untyped. So typescript has no reason to infer name as 'Liverpool' | 'Man Utd' so it infers it as string. When you later try to assign initialFixtures with its inferred type to Fixture[] the assignment fails (since string is not assignable to Team):

type Team =  'Liverpool' | 'Man Utd';

type Fixtures = {
    teams: {
        home: {
            name: Team;
        },
        away: {
            name: Team;
        },
    };
    winner: Team;
};

const initialFixtures= [
    {
        teams: {
            home: {
                name: 'Liverpool',
            },
            away: {
                name: 'Man Utd',
            },
        },
        winner: 'Liverpool',
    },
];
let o: Fixtures[] = initialFixtures; // error here 
// Type '{ teams: { home: { name: string; }; away: { name: string; }; }; winner: string; }[]' is not assignable to type 'Fixtures[]'.

The simple solution is to type initialFixtures and not ask the compiler to infer anything and just check the object literal):

const initialFixtures: Fixtures[]= [
    {
        teams: {
            home: {
                name: 'Liverpool',
            },
            away: {
                name: 'Man Utd',
            },
        },
        winner: 'Liverpool',
    },
];
let o: Fixtures[] = initialFixtures; //ok

Upvotes: 1

Pandelis
Pandelis

Reputation: 1968

type Team = 'Liverpool' | 'Man Utd';

Reason is typescript thinks that your structure should be:

            home: {
                name: {
                   name: 'Liverpool'
                }
            },
            away: {
                name: {
                   name: 'Man Utd'
                }
            },

Alternatively you could keep the team type the same but change the Fixtures type to:

type Fixtures = {
    teams: {
        home: Team;
        away: Team;
        winner: Team;
    };
};

Keep in mind that winner will be an object of {name: 'Teamname'} Not a string of the team name

Upvotes: 0

Carl Pryke
Carl Pryke

Reputation: 349

For one thing, the shape of your data isn't matching up:

Notice you are using 'term' instead of 'away' in your initialFixtures array, and then 'away' instead of 'name'. So you shapes are not matching up. It may help to declare your initialFixtures const as a Fixtures[] as typescript will probably not implicitly realise that.

It looks like useState is a polymorphic function that takes an array of the assigned type Fixtures or a callback that returns the Fixtures[] type.

So as far as I can tell:

term: {
  away: 'Man Utd',
}, 

Should be

away: {
  name: 'Man Utd'
}

Upvotes: 0

Related Questions