简体   繁体   中英

Dynamically accessing properties in TypeScript

I'm new to TypeScript and am trying to access the property of an object by a string. Here is a sandbox showing my problem: https://codesandbox.io/s/optimistic-mendel-f1zdg?file=/src/App.tsx

Code snippet (App.tsx: 17): newFlags[event.target.name] = event.target.value;

Error : Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ hidden: string; completed: string; }'.

I can make the error go away by adding an if statement like if(event.target.name === hidden || event.target.name === "completed") but that solution seems really hard to scale. It seems great if I could use the <Flag> type as a variable, but that seems to make TypeScript mad.

Is there a DRY solution to fixing this error?

This error makes sense since TS is a compiler, it can't know the exact runtime type of target.name , if you are sure it's one of the Flag keys, you should specify it:

// const flag = event.target.name as 'hidden' | 'completed';
const flag = event.target.name as keyof Flag
return { ...prevFlags, [flag]: event.target.value };

One approach is to declare the handler inline, and take the key from the outer scope instead of from the event target:

  for (const [key, value] of Object.entries(flags)) {
    flagSelectors.push(
      <FlagFiltering
        key={key}
        name={key}
        value={value}
        handleChange={(e) => setFlags({
          ...flags,
          [key]: e.target.value
        })}
      />
    );
  }

I'd also recommend avoiding the mutator method .push if something more appropriate exists, like .map :

  return (
    <div className="App">{
      Object.entries(flags).map(([key, value]) => (
          <FlagFiltering

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM