Bhuwan Adhikari
Bhuwan Adhikari

Reputation: 1009

Type 'string' is not assignable to type 'SOME TYPE', small confusion when passing props

Below is how I am using my reusable component Badge made by me. It has types of props as follows but this gives some kind of error as:

enter image description here

Here is full code,

const variantsMap = {
  done: "success",
  processing: "info",
  suspened: "warning",
  cancelled: "error",
};

interface ITransactionProps {
  status: "done" | "processing" | "suspened" | "cancelled";
  label: string;
}

const MyComponent = ({ status, label }: ITransactionProps) => {
  return <Badge variant={variantsMap[status]}>{label}</Badge>;
};

interface IBadgeProps {
  variant: "success" | "info" | "warning" | "error";
  children: string;
}

const Badge = ({ variant, children }: IBadgeProps) => {
  return <div className={`badge bordered circular ${variant}`}>{children}</div>;
};

How can this be solved in proper way? I would like to know all the ways if we can solve it in multiple ways.

Upvotes: 0

Views: 1846

Answers (3)

Samuli Hakoniemi
Samuli Hakoniemi

Reputation: 19059

Here's one way to do it: TypeScript Playground

The full code looks like this:

import React from 'react';

type Variant = "done" | "processing" | "suspened" | "cancelled";

const variantsMap: Record<Variant, string> = {
  done: "success",
  processing: "info",
  suspened: "warning",
  cancelled: "error",
};

interface ITransactionProps {
  status: Variant;
  label: string;
}

const MyComponent = ({ status, label }: ITransactionProps) => {
  return <Badge variant={variantsMap[status]}>{label}</Badge>;
};

interface IBadgeProps {
  variant: string;
  children: JSX.Element | string;
}

const Badge = ({ variant, children }: IBadgeProps) => {
  return <div className={`badge bordered circular ${variant}`}>{children}</div>;
};

Upvotes: 0

tenshi
tenshi

Reputation: 26404

A nice simple and clean solution is to use as const:

const variantsMap = {
  done: "success",
  processing: "info",
  suspened: "warning",
  cancelled: "error",
} as const;

Now variantsMap is typed as:

{
    readonly done: "success";
    // ...
}

which means accessing properties results in literal types, not string which was the cause of the error.

Upvotes: 1

Daniel A. White
Daniel A. White

Reputation: 191058

You can declare variantsMap a bit differently

const variantsMap: Record<string, "success" | "info" | "warning" | "error"> = ...

I would extract that into a new type for readability.

type Variant = "success" | "info" | "warning" | "error";

const variantsMap: Record<string, Variant> = ...

interface IBadgeProps {
  variant: Variant;
  children: string;
}

Upvotes: 1

Related Questions