Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting "Type 'String[] | undefined' is not an array type." for my object variable?

I am trying to create a state variable named hidden to be a dictionary (ex: [{'cutomkey1':'somevalue', 'customkey2':'somevalue'}]). hidden can be empty [{}].

In one of my methods I want to push an item {'asd':'asd'} to the hidden state variable and add them up.

I keep getiting this error:

Type 'String[] | undefined' is not an array type.

I'm new to typescript and I am not sure i set all the variables correctly. this is my code (only the relevant parts):

import React from 'react';

export type AppState = {
    tickets?: Ticket[],
    hidden?: Array<String>,
    search: string;
}

export class App extends React.PureComponent<{}, AppState> {

    state: AppState = {
        search: '',
        hidden: [] 
    }

    hideCard = (e: React.SyntheticEvent<EventTarget>) => {
        let targ = e.target as HTMLElement
        let parent = targ.parentElement as HTMLElement  
        let dict: Map<string, string> = new Map();
        dict.set(parent.id, parent.id)
        this.setState({
            hidden: [...this.state.hidden, {dict}]
        })
        console.log(this.state.hidden)
        parent.classList.add('hideTkt')
    }



}

export default App;

new code:

export type AppState = {
    tickets?: Ticket[],
    hidden?: Array<String> | undefined,
    search: string;
}

export class App extends React.PureComponent<{}, AppState> {

    state: AppState = {
        search: '',
        hidden: [] 
    }


    hideCard = (e: React.SyntheticEvent<EventTarget>) => {
        let targ = e.target as HTMLElement
        let parent = targ.parentElement as HTMLElement  
        let dict: Map<string, string> = new Map();
        dict.set(parent.id, parent.id)
        if (this.state.hidden) {
            this.setState({
                hidden: [...this.state.hidden, {dict}]
            })
        }
        console.log(this.state.hidden)
        parent.classList.add('hideTkt')
    }

this is the error:

Type '(String | { dict: Map<string, string>; })[]' is not assignable to type 'String[]'. Type 'String | { dict: Map<string, string>; }' is not assignable to type 'String'. Type '{ dict: Map<string, string>; }' is not assignable to type 'String'. Object literal may only specify known properties, and 'dict' does not exist in type 'String'.

like image 752
Imnotapotato Avatar asked Jul 18 '26 08:07

Imnotapotato


2 Answers

The declaration hidden?: Array<String>, means that the property could either be a Array<String> OR undefined.

Using the property like this will fail:

hidden.push(item)

because hidden could be undefined (and undefined has no property push).

If you check if this.state.hidden is available, typescript won't complain anymore:

if(this.state.hidden)
  this.setState({
              hidden: [...this.state.hidden, {dict}]
          })

or you can provide a default value using nullish concealing:

...(this.state.hidden ?? [])

If you read attentively the code that creates your 'hidden' array ,

     if (this.state.hidden) {
            this.setState({
                hidden: [...this.state.hidden, {dict}]
            })
        }

you can see that you spread the state.hidden elements (no pb with those , they already are of the correct type, any type, we don't matter ,as they are coming from a previous well typed and built array ),but, then you add a litteral object who has a property called dict , of type Map<string, string>.

This means your array will contain objects that have a "dict" property respecting this interface :{dict:Map<string,string>} . This is why you have this strange error message about this object litteral with a dict property which does not exist on type string (obviously, the items in your array are not strings)

What you can do is :

  1. type hidden as an Array<{dict:Map<string,string>}>.
  2. spread the content of Map<string,string> inside your array when building it (hidden : [...this.state.hidden,...dict]) , which will leads you to have an Array<Record<string,string>> (Record<K,V> being the type of each key value pair item you have in your Map)
  3. create an interface like :
    interface MyInterface
     { 
      dict:Map<string,string>;
    }

then type your array as Array <MyInterface>

  1. Use the Array.from(dict.entries()) méthod to get an array of tuples ([key:string,value:string]), then use the array map operator to transform your entries into something that feets your needs better in this situation (maybe the string you wanted in the first place) by concatening the key and the value of each tuple item (or anything else that gives you a unique string). In another way, if you just keep the array that you get from "Array.from" , you will have the kind of structure you want (an array of keyValue Pair tuples)

There are lots of other options , but those are the main tracks you can follow . And , at the end , if you really want your "hidden" state variable to be a dictionary ,type it as a Map<string,string> from the beginning , and when you reaffect-it , just do

     if (this.state.hidden) {
            this.setState({
                hidden: new Map([...Array.from(this.state.hidden.entries()), ...Array.from(dict.entries())])
            })
        }

You don't have to do all this gym if you target ES6 , as this will work :

     if (this.state.hidden) {
            this.setState({
                hidden: new Map([...this.state.hidden, ...dict])
            })
        }

And , BTW , I think when you set the objects in your Map , you want to do dict.set(target.id, parent.id) instead of dict.set(parent.id, parent.id) .If not , what's the point of using a Map here ?

like image 33
Karlatt Itude Avatar answered Jul 19 '26 22:07

Karlatt Itude



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!