What is the best way to implement an interface for accurately checking each prop type?

Currently, while working with Typescript, I am looking for a solution to define an interface with specific properties inside my object of marks. At the moment, I am using "any", but I know there must be a better approach. Any guidance or advice on how to proceed would be greatly appreciated. Thank you in advance for your help and suggestions.

Below, I have shared both the error message and my code. As I strive to improve in TS, it would be immensely helpful to understand how to resolve this issue.

Error:

Type '{ highlight: ({ children }: { children: any; }) => Element; buttonLink: ({ text, value }: any) => Element; internalLink: ({ text, value }: any) => Element; link: ({ children, value }: any) => Element; }' is not assignable to type 'marksProps'.
  Object literal may only specify known properties, and 'highlight' does not exist in type 'marksProps'.ts(2322)

Code:

import Link from "next/link";

import { Warning } from "phosphor-react";

interface marksProps {
  children?: any;
}

export const marks: marksProps = {
  highlight: ({ children }) => <mark>{children}</mark>,

  buttonLink: ({ text, value }: any) => {
    const title = value?.colors?.title;
    const path = value?.path;

    /* prettier-ignore */
    const Theme : { [key: string]: any } = {
      neon      : "bg-neon text-navyBlue border-navyBlue hover:bg-offWhite",
      clear     : "bg-transparent text-white border-white hover:bg-offWhite hover:text-navyBlue",
      bubblegum : "bg-bubblegum text-navyBlue border-navyBlue hover:bg-offWhite hover:text-navyBlue",
      sand      : "bg-sand text-navyBlue border-navyBlue hover:bg-offWhite hover:text-navyBlue",
      navyBlue  : "bg-navyBlue text-white border-white hover:bg-offWhite hover:text-navyBlue"
    };

    const Button = () => (
      <>
        {path ? (
          <Link href={value.path}>
            <a
              className={`inline-flex items-center px-4 py-2 mt-6 text-xs font-bold text-center uppercase duration-300 ease-in-out border-2 rounded-full ${Theme[title]}`}
            >
              {text}
            </a>
          </Link>
        ) : (
          <div className="block mt-4">
            <p className="flex gap-2 text-sm font-bold text-sand place-items-center">
              <Warning size={24} color="#ffd662" weight="duotone" />
              <span>Page reference URL is required.</span>
            </p>

            <button
              disabled
              className="inline-flex items-center px-4 py-2 mt-3 text-xs font-bold text-center uppercase duration-300 ease-in-out border-2 rounded-full disabled:bg-gray-700 disabled:opacity-30"
            >
              {text}
            </button>
          </div>
        )}
      </>
    );

    return <Button />;
  },

  internalLink: ({ text, value }: any) => {
    return (
      <Link href={value.path}>
        <a className="underline cursor-pointer text-bubblegum">{text}</a>
      </Link>
    );
  },

  link: ({ children, value }: any) => {
    const blank = value.blank;

    return blank ? (
      <a
        className="underline cursor-pointer text-bubblegum"
        href={value.href}
        rel="noreferrer"
        target="_blank"
      >
        {children}
      </a>
    ) : (
      <a
        className="underline cursor-pointer text-bubblegum"
        href={value.href}
        rel="noreferrer"
      >
        {children}
      </a>
    );
  },
};

Answer №1

In order to make the necessary changes, you should adjust the children property to be an array of React.ReactNode. Additionally, ensure that you assign your type, marksProps, to the props of the marks arrow function props rather than the constant.

import React from "react";
import { Warning } from "phosphor-react";

interface marksProps {
  children?: React.ReactNode[];
}

export const marks = {
  highlight: ({ children }: marksProps) => <mark>{children}</mark>,

  buttonLink: ({ text, value }: any) => {
    const title = value?.colors?.title;
    const path = value?.path;

    /* prettier-ignore */
    const Theme : { [key: string]: any } = {
      neon      : "bg-neon text-navyBlue border-navyBlue hover:bg-offWhite",
      clear     : "bg-transparent text-white border-white hover:bg-offWhite hover:text-navyBlue",
      bubblegum : "bg-bubblegum text-navyBlue border-navyBlue hover:bg-offWhite hover:text-navyBlue",
      sand      : "bg-sand text-navyBlue border-navyBlue hover:bg-offWhite hover:text-navyBlue",
      navyBlue  : "bg-navyBlue text-white border-white hover:bg-offWhite hover:text-navyBlue"
    };

    const Button = () => (
      <>
        {path ? (
          <Link href={value.path}>
            <a
              className={`inline-flex items-center px-4 py-2 mt-6 text-xs font-bold text-center uppercase duration-300 ease-in-out border-2 rounded-full ${Theme[title]}`}
            >
              {text}
            </a>
          </Link>
        ) : (
          <div className="block mt-4">
            <p className="flex gap-2 text-sm font-bold text-sand place-items-center">
              <Warning size={24} color="#ffd662" weight="duotone" />
              <span>Page reference URL is required.</span>
            </p>

            <button
              disabled
              className="inline-flex items-center px-4 py-2 mt-3 text-xs font-bold text-center uppercase duration-300 ease-in-out border-2 rounded-full disabled:bg-gray-700 disabled:opacity-30"
            >
              {text}
            </button>
          </div>
        )}
      </>
    );

    return <Button />;
  },

  internalLink: ({ text, value }: any) => {
    return (
      <Link href={value.path}>
        <a className="underline cursor-pointer text-bubblegum">{text}</a>
      </Link>
    );
  },

  link: ({ children, value }: any) => {
    const blank = value.blank;

    return blank ? (
      <a
        className="underline cursor-pointer text-bubblegum"
        href={value.href}
        rel="noreferrer"
        target="_blank"
      >
        {children}
      </a>
    ) : (
      <a
        className="underline cursor-pointer text-bubblegum"
        href={value.href}
        rel="noreferrer"
      >
        {children}
      </a>
    );
  },
};

TypeScript Playground Link

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it Feasible to Use Component Interface in Angular 5/6?

My main goal is to create a component that can wrap around MatStepper and accept 2..n steps, each with their own components. In other languages, I would typically create an interface with common behavior, implement it in different components, and then use ...

Stop committing changes in Git when there are any TypeScript errors found

While working on my project in TypeScript using Visual Code, I encountered a situation where I was able to commit and push my changes to the server through Git (Azure) even though there was an error in my code causing a build failure. It made me wonder i ...

Can you identify the specific error type that occurs in the onError function of react-query's MutationCache when using Typescript

Can someone help me with identifying the type of error in react-query MutationCache onError function when using Typescript? I also need guidance on how to override the type so that I can access and use the fullMessage from the data. const queryClient = new ...

What is the reason that setState functions properly when parsing each key separately, but fails when passed as an object?

Currently, I am delving into the world of React and TypeScript, but I have encountered a problem when trying to pass an object with a specific type in order to update the state. For some reason, the state remains unchanged. My approach involves using the ...

What is the best way to process a date string and format it in TypeScript?

My task involves receiving a date in string format as 20160229000000 ('YYYYMMDDhhmmss'). I need to take this string and display it in DD-MON-YYYY format using Typescript. Instead of relying on an angular package like DatePipe, I am working with ...

Follow these steps to incorporate the Tailwind CSS scroll-smooth class into your Next.js project

I'm seeking to incorporate smooth scrolling behavior into my Next.js application. According to the Tailwind CSS documentation, we need to add the utility class within the <html/> tag. <html class="scroll-smooth "> <! ...

Tips for troubleshooting a React Native project built with Expo and utilizing TypeScript

I started a new Expo project with TypeScript integration. After launching the app using expo start, I noticed that the Chrome debugger only displays .js files at http://localhost:19001/debugger-ui/: https://i.stack.imgur.com/cmyy9.png How can I make sur ...

Developing React components with Typescript requires careful consideration when defining component props, especially when the component may be

Consider the following scenario: { this.props.userName && <UserProfile userName={this.props.userName} /> In the UserProfile component: interface UserProfileProps { userName: string; } class UserProfile extends React.Component<UserProfile ...

Encountering problems with createMediaElementSource in TypeScript/React when using the Web Audio API

Currently, I am following a Web Audio API tutorial from MDN, but with a twist - I am using TypeScript and React instead of vanilla JavaScript. In my React project created with create-react-app, I am utilizing the useRef hook to reference the audio element ...

Unable to locate the "fcm-node" module in Node.js with TypeScript

When working on a TypeScript project, I usually rely on the fcm-node package to send Firebase push notifications in Node.js. However, this time around, I faced an issue. I know that for TypeScript projects, we also need to install type definitions (@types ...

Tips for type guarding in TypeScript when using instanceof, which only works with classes

Looking for a way to type guard with TypeScript types without using instanceof: type Letter = 'A' | 'B'; const isLetter = (c: any): c is Letter => c instanceof Letter; // Error: 'Letter' only refers to a type, but is being ...

Issues with cookies are preventing functionality when accessing a developmental version of a Next application on a mobile device

During testing of my Next JS development build on a mobile phone, I accessed it using a private IP address (192.XXX.X.24:3000) rather than localhost:3000 on my development machine. The pages load correctly, but when attempting to send cookies back to the b ...

Tips for adding and verifying arrays within forms using Angular2

Within my JavaScript model, this.profile, there exists a property named emails. This property is an array composed of objects with the properties {email, isDefault, status}. Following this, I proceed to define it as shown below: this.profileForm = this ...

The error message "Unable to access property 'slideHandler' of null in react-slick" is displayed

My current component utilizes two sliders in total (4 in combination) - one for horizontal carousel and the other for vertical, based on screen size. On smaller devices, it works perfectly fine, but on larger screens, it renders initially but crashes when ...

What is the process for obtaining a client-side cookie using next.js?

I'm currently facing an issue where I can't seem to maintain a constant value for the isAuthenticated variable between server-side and client-side in next.js. In my setup, I am using a custom app.js file to wrap the app with Apollo Provider. The ...

Creating a dynamic array in an Angular 2 service for real-time changes monitoring by a component

I am facing an issue where my NotificationsBellComponent is not receiving changes to the array in the service even though the _LocalStorageService is returning data correctly. Q) How can I ensure that my component receives updates when the service collect ...

Changing function arguments in TypeScript using the spread operator

Could the Tuple spreading syntax in Typescript be utilized to consolidate these function overloads? The challenge lies in the necessity to refactor the function arguments into new types. type Type = TString | TNumber type TString = { tag: 'string&apos ...

Error in TypeScript when utilizing an Enum as a string

Attempting to include a string enum in my Angular 2 project resulted in an error during the npm project startup: ERROR in e:/projects/dbtool-fullstack/dbtool-client/src/app/shared/models/full-m odels/enums/Sex.ts (2,10): Type '"Male"' is not ass ...

Is there a point in bundling NPM packages if they are ultimately going to be bundled by the project

I'm in the process of creating a TypeScript package for publication on NPM. My plan is to utilize this package in upcoming web development endeavors, most likely utilizing Vite. As I look ahead to constructing a future website with this module, I am c ...

Adding items to the array is only effective when done within the loop

My approach involves retrieving data from an API using axios, organizing it within a function named "RefractorData()," and then pushing it onto an existing array. However, I have encountered a problem where the array gets populated within a forEach loop, a ...