简体   繁体   中英

Type 'string' is not assignable to type '“x” | “y” | “z”'. TS2345

Here is the interface I'm working with:

export default interface BodyInterface {
  cover : { name: string, element: JSX.Element },
  portfolio : { name: string, element: JSX.Element },
  aboutContact : { name: string, element: JSX.Element },
}

The error:

/home/owner/cp/portfolioSite/src/utilities.tsx
TypeScript error in /home/owner/cp/portfolioSite/src/utilities.tsx(19,53):
Argument of type '(keyName: "cover" | "portfolio" | "aboutContact") => JSX.Element' is not assignable to parameter of type '(value: string, index: number, array: string[]) => Element'.
  Types of parameters 'keyName' and 'value' are incompatible.
    Type 'string' is not assignable to type '"cover" | "portfolio" | "aboutContact"'.  TS2345

    17 |   const allKeys: Array<string> = Object.keys(jsxData);
    18 | 
  > 19 |   const linkComponents: JSX.Element[] = allKeys.map((keyName: keyof BodyProps) => {
       |                                                     ^
    20 |     const linkComponent: JSX.Element = makeLink(jsxData[keyName].name);
    21 |     return linkComponent;
    22 |   })

The surrounding context:

import BodyProps from './bodySection/BodyPropInterface';

export function makeLink(linkName: string): JSX.Element {
  return (
  <Link to={linkName}>{titleFirstCharacter(linkName)}</Link>
  )
}

export function makeAllLinks(jsxData: BodyProps) {
  const allKeys: Array<string> = Object.keys(jsxData);

  const linkComponents: JSX.Element[] = allKeys.map((keyName: keyof BodyProps) => {
    const linkComponent: JSX.Element = makeLink(jsxData[keyName].name);
    return linkComponent;
  })

  return linkComponents;
}

But if I annotate keyName: string I get this error instead:

/home/owner/cp/portfolioSite/src/utilities.tsx
TypeScript error in /home/owner/cp/portfolioSite/src/utilities.tsx(20,49):
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'BodyInterface'.
  No index signature with a parameter of type 'string' was found on type 'BodyInterface'.  TS7053

    18 | 
    19 |   const linkComponents: JSX.Element[] = allKeys.map((keyName: string) => {
  > 20 |     const linkComponent: JSX.Element = makeLink(jsxData[keyName].name);
       |                                                 ^
    21 |     return linkComponent;
    22 |   })
    23 | 

What is the correct way to solve this error?

So it looks like your error is coming from the makeAllLinks function.

export function makeAllLinks(jsxData: BodyProps) {
  const allKeys: Array<string> = Object.keys(jsxData); /// <---- This piece

  const linkComponents: JSX.Element[] = allKeys.map((keyName: keyof BodyProps) => {
    const linkComponent: JSX.Element = makeLink(jsxData[keyName].name);
    return linkComponent;
  })

  return linkComponents;
}

The right type should be:

Array<keyof BodyProps>

Something like:

const allKeys: Array<keyof BodyProps> = Object.keys(jsxData);

After that change I still get an issue. It looks like Object.keys will always just return an array of strings, and it doesn't take a generic you can pass in to change that. So you can typecast it, to look like:

const allKeys = Object.keys(jsxData) as Array<keyof BodyProps>;

Then you should be able to map over it, and have the right values come up.

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