1

I have a container as follows:

lass BurgerBuilder extends React.Component {

state = {
    ingredients: {
        salad: 1,
        bacon: 1,
        cheese: 2, 
        meat: 2
    }
}
render() {
    return(
        <>
            <Burger ingredients={this.state.ingredients}/>
            <div>Build Controls</div>
        </>
    );
}
}

My Burger functional component includes the following code

export interface IBurgerProps {
    ingredients: {
        salad?: number,
        bacon?: number,
        cheese?: number, 
        meat?: number
    }
}

const burger = (props: IBurgerProps) =>{
    const transformedIngredients = Object.keys(props.ingredients).map(igKey=> {
        return [...Array(props.ingredients[igKey])].map((_, i) => {
            <BurgerIngredient key={igKey + i} type={igKey}/>
        })
    });

Theoretically, if I add "chicken: 1" to the ingredient object in my container (BurgerBuilder), I should get an error. I.e, typescript should complain saying we can't assign { salad: number, bacon: number, cheese: number, meat: number, chicken: number } to type { salad: number | undefined, bacon: number | undefined, cheese: number | undefined, meat: number | undefined}

Why is it that I don't get this error when I add "chicken: 1" to the ingredients object in Burger Builder?

Just trying to understand typing and react more.

1 Answer 1

3

TypeScript uses what's called a substructural type system, which means as long as your object has everything you asked from it, the rest doesn't really matter.

There is an ongoing discussion around the topic of introducing exact types to the language. Today one needs to employ some questionable tricks to make it work.

In the meantime, I recommend describing the contract between your components with an interface. In this case, Ingredients are the interface — it's what both components depend on.

Let's abstract it from your component. An example model could look like this:

type IngredientName =
  | 'salad'
  | 'bacon'
  | 'cheese'
  | 'meat';

type Ingredients = Record<IngredientName, number>

Usage:

interface Props {}

interface State {
    ingredients: Ingredients;
}

export class BurgerBuilder extends React.Component<Props, State> {
    state: State = {
        ingredients: {
            salad: 1,
            bacon: 1,
            cheese: 2,
            meat: 2,
            chicken: 2, // Error! Chicken is not on the list.
        },
    };
}

You can read more about type relationships in the specification.

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

Comments

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.