0

Button

import React from 'react';
import './button.css';

interface ButtonProps {
  primary?: boolean;
  backgroundColor?: string;
  size?: 'small' | 'medium' | 'large';
  label: string;
  onClick?: () => void;
}

export const Button = ({
  primary = false,
  size = 'medium',
  backgroundColor,
  label,
  ...props
}: ButtonProps) => {
  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
  return (
    <button
      type="button"
      className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
      style={{ backgroundColor }}
      {...props}
    >
      {label}
    </button>
  );
};

Button.stories

import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';

import { Button } from '.';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
} as ComponentMeta<typeof Button>;

const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
};

...

Button.test

import { render } from '@testing-library/react';
import { Button } from '.';
import { Primary } from './Button.stories';

test('should render a button', () => {
  render(<Button label="Click Me!" />);
});

test('should render a primary button', () => {
  if (typeof Primary.args === 'undefined') {
    throw new Error('Args is undfeined');
  } else if (typeof Primary.args.label !== 'string') {
    throw new Error('The type of label is not string');
  } else if (Primary.args.label === undefined) {
    return;
  }

  /** 
      Types of property 'label' are incompatible.
      Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.
   */
  render(<Primary {...Primary.args} />);
});

I wrote some test code for the button component that was made by Storybook default. Even though I already checked the type of the label prop if the type is undefined or not before the props are delivered, it throws a syntax error 'string | undefined' is not assignable to type 'string'.

Why did I do wrong?

1 Answer 1

2

This is a similar question to this:

Typescript: Type 'string | undefined' is not assignable to type 'string'

You can either use a Non-Null Assersion ( ! )

OR

You can use a logical-OR Expression Operator to state an optional value ( || )

(There are other methods too, although these are often the most popular)

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't need a solution, I wondered why the error occurred, even I checked all ways ( i think),
ButtonProps you've defined stated label must strictly only allow assignment as a string type. Even though you've confirmed in your test that the value you're passing to label is a string, unless you disable strict mode you'll get this error message when your typescript is transpiled as there's no strict typing of Primary.args.label to never be undefined (it has the type string | undefined as far as the transpiler is aware) You need to use an operator stating that either you're certain it won't be undefined or it won't cause errors, or use an OR and handle the undefined case to clear it
I got to know it's a way that typescript works. Thanks for the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.