最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Source has 2 element(s) but target allows only 1. Typescript spread operator - Stack Overflow

programmeradmin1浏览0评论

I'm trying to spread all values in array and append a new object in my reducer.

my state interface:

export interface IBasketState {
products: [
    {
        id: number | undefined;
        name: string;
        smallQ: number; //small packages quantity
        smallTotalP: number; //price for all small packages
        largeQ: number; //large packages quantity
        largeTotalP: number; //price for all large packages
        orderPrice: number; //total price of this order
    }
  ];
    totalPrice: number;
}

Reducer add item function:

const BasketReducer = (basketState: IBasketState, action: IBasketAction): IBasketState => {
//ADD ITEM
if (action.type === "Add item") {
    const { id, name, smallQ, smallP, largeQ, price } = action.payload;
    let smallTotalPrice = smallQ * smallP; //total price for small packages
    let largeTotalPrice = largeQ * price; //total price for large packages
    const orderPrice = smallTotalPrice + largeTotalPrice; //total price of this order
    return {
        products: [
    ...basketState.products, //--> **THIS IS NOT WORKING**
            {
                id: id,
                name: name,
                smallQ: smallQ,
                smallTotalP: smallTotalPrice,
                largeQ: largeQ,
                largeTotalP: largeTotalPrice,
                orderPrice: orderPrice,
            },
        ],
        totalPrice: basketState.totalPrice + orderPrice,
    };
}
//Default action
return basketState;
};

When I hover over ...basketState.products I've got an error saying:

Type '[{ id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }, { id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }]' is not assignable to type '[{ id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }]'.

Source has 2 element(s) but target allows only 1.ts(2322)

BasketContext.tsx(8, 2): The expected type es from property 'products' which is declared here on type 'IBasketState'

Is the problem the fact that in my interface I have declared only one object in products array and I'm trying to have 2 now? If so how can I bypass that?

I'm trying to spread all values in array and append a new object in my reducer.

my state interface:

export interface IBasketState {
products: [
    {
        id: number | undefined;
        name: string;
        smallQ: number; //small packages quantity
        smallTotalP: number; //price for all small packages
        largeQ: number; //large packages quantity
        largeTotalP: number; //price for all large packages
        orderPrice: number; //total price of this order
    }
  ];
    totalPrice: number;
}

Reducer add item function:

const BasketReducer = (basketState: IBasketState, action: IBasketAction): IBasketState => {
//ADD ITEM
if (action.type === "Add item") {
    const { id, name, smallQ, smallP, largeQ, price } = action.payload;
    let smallTotalPrice = smallQ * smallP; //total price for small packages
    let largeTotalPrice = largeQ * price; //total price for large packages
    const orderPrice = smallTotalPrice + largeTotalPrice; //total price of this order
    return {
        products: [
    ...basketState.products, //--> **THIS IS NOT WORKING**
            {
                id: id,
                name: name,
                smallQ: smallQ,
                smallTotalP: smallTotalPrice,
                largeQ: largeQ,
                largeTotalP: largeTotalPrice,
                orderPrice: orderPrice,
            },
        ],
        totalPrice: basketState.totalPrice + orderPrice,
    };
}
//Default action
return basketState;
};

When I hover over ...basketState.products I've got an error saying:

Type '[{ id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }, { id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }]' is not assignable to type '[{ id: number | undefined; name: string; smallQ: number; smallTotalP: number; largeQ: number; largeTotalP: number; orderPrice: number; }]'.

Source has 2 element(s) but target allows only 1.ts(2322)

BasketContext.tsx(8, 2): The expected type es from property 'products' which is declared here on type 'IBasketState'

Is the problem the fact that in my interface I have declared only one object in products array and I'm trying to have 2 now? If so how can I bypass that?

Share Improve this question asked Jul 2, 2021 at 10:44 MadGripMadGrip 4716 silver badges21 bronze badges 1
  • 1 Does this help stackoverflow./questions/64308563/… ? – Tushar Shahi Commented Jul 2, 2021 at 10:47
Add a ment  | 

2 Answers 2

Reset to default 5

Your guess is correct: the products property is typed as a tuple containing exactly one element.

What you could try is to turn it into an array of products:

interface BasketState {
    products: Product[];
    totalPrice: number;
}

interface Product {
    id: number | undefined;
    name: string;
    smallQ: number;
    smallTotalP: number;
    largeQ: number;
    largeTotalP: number;
    orderPrice: number;
}

You can read more on the tuple types in TypeScript here: https://www.typescriptlang/docs/handbook/2/objects.html#tuple-types

You have declared products as a tuple with a single object ([T]), instead of a list (T[] or Array<T>). So in other words, what you want is:

export interface IBasketState {
products: Array<{
        id: number | undefined;
        name: string;
        smallQ: number; //small packages quantity
        smallTotalP: number; //price for all small packages
        largeQ: number; //large packages quantity
        largeTotalP: number; //price for all large packages
        orderPrice: number; //total price of this order
    }>;
    totalPrice: number;
}

Sometimes, it can be nicer to define the type of the item instead of the list, so that your interface can look like this:

export interface IProduct = {
    id: number | undefined;
    name: string;
    smallQ: number; //small packages quantity
    smallTotalP: number; //price for all small packages
    largeQ: number; //large packages quantity
    largeTotalP: number; //price for all large packages
    orderPrice: number; //total price of this order
}

export interface IBasketState {
    products: IProduct[];
    totalPrice: number;
}
发布评论

评论列表(0)

  1. 暂无评论