Home > Enterprise >  Typescript error: Argument of Type X is not assignable to parameter of type Y
Typescript error: Argument of Type X is not assignable to parameter of type Y

Time:11-26

New to Typescript, and trying to understand how I can fix the below errors. If I remove the ItemProps as props, lg and md are highlighted and the following error shows:

Type 'string' is not assignable to type 'ColSpec | undefined'.ts(2322)

So then I try to extend the ColProps, and then I get

Argument of type '(item: Item) => JSX.Element' is not assignable to parameter of type '(value: { title: string; content: string; social: { title: string; link: string; }[]; lg: string; links?: undefined; md?: undefined; contentBottomMargin?: undefined; form?: undefined; } | { title: string; links: { ...; }[]; ... 5 more ...; form?: undefined; } | { ...; }, index: number, array: ({ ...; } | ... 1 more ...'.
  Types of parameters 'item' and 'value' are incompatible.
    Type '{ title: string; content: string; social: { title: string; link: string; }[]; lg: string; links?: undefined; md?: undefined; contentBottomMargin?: undefined; form?: undefined; } | { title: string; links: { ...; }[]; ... 5 more ...; form?: undefined; } | { ...; }' is not assignable to type 'Item'.
      Type '{ title: string; content: string; social: { title: string; link: string; }[]; lg: string; links?: undefined; md?: undefined; contentBottomMargin?: undefined; form?: undefined; }' is not assignable to type 'Item'.
        Property 'md' is optional in type '{ title: string; content: string; social: { title: string; link: string; }[]; lg: string; links?: undefined; md?: undefined; contentBottomMargin?: undefined; form?: undefined; }' but required in type 'Item'.`

See code below:

Footer.tsx file

import {
  Container,
  Row,
  Col,
  ColProps
} from "react-bootstrap";

import footerContent from "./footer.json";

interface Item extends ColProps {
  lg: string | ColProps["lg"];
  md: string | ColProps["md"];
}

const Footer = () => {
  return (
    <Container>
      <Row>
        {footerContent.map((item) => (
          <Col
            key={item.title}
            lg={item.lg && item.lg}
            md={item.md && item.md}
            className="mb-5 mb-lg-0"
          >
            <div className="fw-bold text-uppercase text-dark mb-3">
              {item.title}
            </div>
          </Col>
        ))}
      </Row>
    </Container>
  );
};

export default Footer;

then footer.json file

[
  {
    "title": "App",
    "lg": "4"
  },
  {
    "title": "Stuff",
    "lg": "2",
    "md": "6"
  }
]

I've taken a look at Overriding interface property type defined in Typescript d.ts file, as well as some other answers, and have tried overriding, extending, omitting, etc. to no avail. What could I do here to get the errors to stop, and the code to work?

CodePudding user response:

I think you are almost there, you just needed to assign the right type to the imported JSON (or you can assign the right type to item in your .map callback.

import React from 'react';
import {
  Container,
  Row,
  Col,
  ColProps
} from "react-bootstrap";

// if you are importing JSON, cast it
// import _footerContent from "./footer.json"; 
// const footerContent = _footerContent as FooterContent[];

type FooterContent = {
  title: string;
  lg: ColProps['lg'];
  md?: ColProps['md'];
}
const footerContent: FooterContent[] = [
  {
    "title": "App",
    "lg": "4"
  },
  {
    "title": "Stuff",
    "lg": "2",
    "md": "6"
  }
];

const Footer = () => {
  return (
    <Container>
      <Row>
        {footerContent.map((item) => (
          <Col
            key={item.title}
            lg={item.lg && item.lg}
            md={item.md && item.md}
            className="mb-5 mb-lg-0"
          >
            <div className="fw-bold text-uppercase text-dark mb-3">
              {item.title}
            </div>
          </Col>
        ))}
      </Row>
    </Container>
  );
};

export default Footer;

TS Playground: https://tsplay.dev/wOzlzW

I also think,

            lg={item.lg && item.lg}
            md={item.md && item.md}

is just verbose without purpose and same as

            lg={item.lg}
            md={item.md}
  • Related