Peter Penzov
Peter Penzov

Reputation: 1754

Spread types may only be created from object type

I have this JavaScript code which I want to use into TypeScript project. But I get these errors. Do you know how I can fix these issues?

const next = () => {
        const data = {
            currency,
            iban,
            confirmIban
        }

        history.push({
            pathname: '/summary',
            state: { ...location.state, ...data }
        })
    }

For this line state: { ...location.state, ...data } I get TS2698: Spread types may only be created from object types.

                   <TextField label="Your test" variant="outlined" onChange={(e) => {
                        setTest(e.target.value)
                    }} />

For this line (e) I get TS7006: Parameter 'e' implicitly has an 'any' type.

EDIT: complete code:

import { useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom'
import { Container, FormControl, Typography, Grid, TextField, Button } from '@material-ui/core';
import SelectOption from '../../components/Navbar/Select/SelectOption';

export default function BankDetails() {
    const [currency, setCurrency] = useState();
    const [iban, setIban] = useState();
    const [confirmIban, setConfirmIban] = useState();

    const history = useHistory();
    const location = useLocation();

    const next = () => {
        const data = {
            currency,
            iban,
            confirmIban
        }

        history.push({
            pathname: '/summary',
            state: { ...location.state, ...data }
        })
    }

    return (
        <Container>
            <Typography variant="h4">Select an account for payouts</Typography>

            <FormControl>
                <Grid xs={12}>
                    <SelectOption handleValue={(e) => {
                        setCurrency(e.target.value)
                    }}>
                        <option value="">Select your currency</option>
                        <option value="lev">USD</option>
                    </SelectOption>
                </Grid>

                <Grid xs={12}>
                    <label>IBAN</label>
                    <TextField label="Your number" variant="outlined" onChange={(e) => {
                        setIban(e.target.value)
                    }} />
                </Grid>

                <Grid xs={12}>
                    <label>Confirm USD</label>
                    <TextField label="Confirm your USD" variant="outlined" onChange={(e) => {
                        setConfirmIban(e.target.value)
                    }} />
                </Grid>
                <Button variant="contained" color="primary" onClick={next}>
                    Continue
                </Button>
            </FormControl>
        </Container>
    )
}

Upvotes: 0

Views: 10411

Answers (2)

Filipe Prado
Filipe Prado

Reputation: 134

Try this aproach, let me know if works.

export interface Location<S = LocationState> {
  pathname: Pathname;
  search: Search;
  state: S as object; 
  hash: Hash;
  key?: LocationKey | undefined;
}

export interface Location<S = LocationState> {
  pathname: Pathname;
  search: Search;
  state: Object.assign({}, S);
  hash: Hash;
  key?: LocationKey | undefined;
}
import { FormEvent } from "react";


<TextField 
  label="Your test"
  variant="outlined"
  onChange={(e: FormEvent<HTMLInputElement>):  => setTest(e.target.value) /> 

Upvotes: 1

Mohammadreza Khedri
Mohammadreza Khedri

Reputation: 2711

1. TS2698: Spread types may only be created from object types.

for this one, you should write your push state with an object.

Note: you should know that location.state is undefined for first and you are using ...location.state in the object but you don't know your state is an object or not. so you should write a simple condition for that.

let prevState = {}
if (location.state) {
    prevState = { ...location.state as {} }
}
history.push({
    pathname: '/summary',
    state: { ...prevState, ...data }
})

2. TS7006: Parameter 'e' implicitly has an 'any' type.

for these parameters, you can simply write any type.

<SelectOption handleValue={(e: any) => {
    setCurrency(e.target.value)
}}>

Or you can add this rule to your tsconfig.json file:

"noImplicitAny": false

Upvotes: 2

Related Questions