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

javascript - Why am I getting "Type 'String[] | undefined' is not an array type." for my objec

programmeradmin6浏览0评论

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'.

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'.

Share Improve this question edited Mar 3, 2021 at 13:32 Imnotapotato asked Mar 3, 2021 at 13:09 ImnotapotatoImnotapotato 5,80814 gold badges84 silver badges156 bronze badges 3
  • Remove the optional modifier hidden: Array<String>, – Roberto Zvjerković Commented Mar 3, 2021 at 13:10
  • @ritaj removing it results 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'. and as said, hidden can be empty, shouldn't this be there ? – Imnotapotato Commented Mar 3, 2021 at 13:13
  • hidden: Array<Record<string, string>> – Roberto Zvjerković Commented Mar 3, 2021 at 13:19
Add a comment  | 

2 Answers 2

Reset to default 12

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 ?

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论