interface Data {
petname: string,
petprice: string,
category: string,
pettype: string,
gender: string,
short: string,
details: string
}
const [petdata, setPetdata] = useState<Data>({});
const [img, setImg] = useState<string>('');
Error: Argument of type '{}' is not assignable to parameter of type 'Data | (() => Data)'. Type '{}' is not assignable to type '() => Data'. Type '{}' provides no match for the signature '(): Data'
CodePudding user response:
Short answer: the empty object you have provided as the default value upon initialisation, {}
, does not match the Data
interface as it is missing all the required properties in it. This is a good sign because that means TypeScript is doing its intended job: ensuring you don't assign objects that does not match the given interface.
Long answer: A solution will be to allow the state to be Data
or null
, so you can just instantiate it with null
at the start until you have populated it later:
const [petdata, setPetdata] = useState<Data | null>(null);
Based on how your downstream code looks like, this change may lead to errors if you attempt to access properties inside the petdata
object, e.g. petdata.petname
, without first checking if petdata
is nullish. This can be circumvented if you:
use the optional chaining operator when accessing sub properties, e.g.
petdata?.petname
, orhave a type guard before accessing any properties, e.g.
if (petdata) { petadata.petname = ...; }
Of course, a dirty escape hatch is to make all properties optional, i.e.:
const [petdata, setPetdata] = useState<Partial<Data>>({});
...but I would not recommend this for your case as that means you are no longer strict enforcing required properties on petdata
, and these properties are likely to be compulsory/required by design.
CodePudding user response:
Unlike in Java for example, Javascript does not really maintain classes at runtime. The TypeScript compiler does. Javascript maintains only "objects" with their properties and values (and methods of course, but in this case you only have properties). Those you defined are all obligatory, none of them are optional.
You can mark a property as optional by adding a ?
behind the variable's name, like this:
details?: string
So the compiler tries to match your parameter {}
to an interface you defined, but nothing matches, because Data
would need all those obligatory properties to match. The method needs either an object of type Data
or a method, that returns a Data
object.
So you've got two options: you define Data
's properties as optional, and therefore let {}
match Data
or pass all the data like this:
{
petname: '',
petprice: '',
category: '',
pettype: '',
gender: '',
short: '',
details: ''
}
CodePudding user response:
Declaring your state as follows will accepts empty objects
const [petdata, setPetdata] = useState<Data>({} as Data);