TypeScript is popularly used for JavaScript extension and data specification in the industry. As it reports unmatched types, writing in TypeScript can ensure productivity and optimal developer experience while coding.

If we are onto using TypeScript, Storybook 7.0 is worth mentioning. That’s because it allows you to write in TypeScript without any configuration setup and boost your experience with built-in APIs. With the launch of Storybook 7.0, the tool rectified all the pain points in the previous version.

Now, you get a combination of CSF 3 and the new TypeScript 4.9+ operator to bolster accuracy and safety. Read on to explore how this combination can make your coding more productive and safer while using the latest Storybook 7.0.

Storybook 7.0 — An Introduction to Update 8/18

Storybook 7.0 or update 8/18 is a core upgrade of Storybook focused on better interaction testing and user experience. You get 3.5% more screen space for Canvas with over 196 icons available for complete customizations.

By the same token, Storybook 7.0 is more compatible in integrating with Remix, Qwik, and SolidJS. The also features some documentation upgrades such as MDX 2 and simplified import of stories. Lastly, the most exclusive upgrade is the combination of TypeScript 4.9+ and CSF3.

Let’s see what makes it a big highlight!

What is TypeScript 4.9+?

TypeScript 4.9+ is a statically-typed superset of JavaScript that provides additional features such as type annotations, interfaces, and generics. It enables developers to write more maintainable and scalable code by catching potential errors at compile-time rather than runtime.

One of the key benefits of using TypeScript with Storybook 7.0 is that it allows developers to specify the expected types of props and events for each component. This ensures that any components that use these props and events are properly typed and provide a clear contract for how they should be used.

In addition to these benefits, TypeScript can also improve the documentation and discoverability of UI components in Storybook 7.0. By leveraging TypeScript’s support for JSDoc annotations, developers can document the expected usage of each component and generate API documentation automatically.

Look at the difference between TypeScript types in Storybook 6 and Storybook 7.0 below.

Combination of CSF3 Syntax and TypeScript 4.9+

In addition to TypeScript 4.9+, the Component Story Format (CSF) also received an upgrade from version CSF 2 to CSF3. The combination of both offer enhanced type safety, better in-editor type checking, and Codemod for easy upgrades.

Here are the top elements of this incredible combination!

StoryObj Type

With the upgrade CSF3, you now get access to the StoryObj type that manipulates stories as objects and infers the type of component props. The feature was still there but the previous story was not so powerful to automatically infer prop types.

On the other hand, this new syntax depreciates React-Specific ComponentMeta and ComponentStory using React, Vue, Svelte, and Angular. Check the result with a side-by-side comparison of CSF2 and CSF3 given below

satisfies Operator

satisfies Operator is the most useful feature of TypeScript 4.9+ for strict type checking. Pair CSF3 with satisfies operator to better type safety and fix unspecified/specified issues. Take a look at the below example where TypeScript is not raising any issue for unspecified label arg.

If you use satisfies operator, you can fix that issue as we did below.

// Button.stories.tsx

import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta = {
  title: 'Example/Button',
  component: Button,
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {
    primary: true,
  },
};

After fixing the issue, you can expect TypeScript to provide an error for unspecified arg.

Auto-infer Component Level args

Pairing the CSF and TypeScript is good but it will not infer the types automatically unless you specify the connection. In this scenario, TypeScript will show errors on the stories even if you have provided a label in meta-level args.

That’s where auto-infer component level args come up to specify the connection between CSF and TypeScript. To make them understand the connection, you need to pass the typeof meta to StoryObj at both story and meta-level. Here’s how you can do it!

// Button.stories.tsx

import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta = {
  title: 'Example/Button',
  component: Button,
  args: {
    label: 'Default',
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

// 👇 TS won't complain about the "label" missing
export const Primary: Story = {
  args: {
    primary: true,
  },
};

const Secondary: Story = {
  args: { disabled: false }
};

const Disabled: Story = {
  args: { disabled: true }
};

Vue

As discussed above, Storybook 7.0 is more compatible with modern frameworks. Vue is the best example of that but you need to set up an ideal environment. Look for SFC files with vue-tsc and access the editor support in VSCode. Take a look at the Vue3 single file component.

<script setup lang="ts">
defineProps<{ count: number, disabled: boolean }>()

const emit = defineEmits<{
  (e: 'increaseBy', amount: number): void;
  (e: 'decreaseBy', amount: number): void;
}>();
</script>

<template>
  <div class="card">
    {{ count }}
    <button @click="emit('increaseBy', 1)" :disabled='disabled'>
        Increase by 1
    </button>
    <button @click="$emit('decreaseBy', 1)" :disabled='disabled'>
        Decrease by 1
    </button> 
  </div>
</template>

Svelte

Like Vue, Svelte features excellent support for TypeScript and enables .svelte files. You can utilize svelte-check and add VSCode editor support to run type checks. Consider the following component as an example.

<script lang="ts">
  import { createEventDispatcher } from 'svelte';

  export let count: number;
  export let disabled: boolean;

  const dispatch = createEventDispatcher();
</script>

<div class="card">
  {count}
  <button on:click={() => dispatch('increaseBy', 1)} {disabled}> Increase by 1 </button>
  <button on:click={() => dispatch('decreaseBy', 1)} {disabled}> Decrease by 1 </button>
</div>

Conclusion:

Conclusively, the new TypeScript 4.9+ features in Storybook 7.0 have greatly improved the type safety and developer experience for creating UI components. With the addition of advanced type inference capabilities, developers can now create reusable components with more confidence, reducing the risk of runtime errors and improving overall code quality.

Overall, the combination of TypeScript 4.9+ and Storybook 7.0 makes for a powerful toolset that empowers developers to create more robust and efficient UI components. As TypeScript continues to evolve, we can expect even more improvements in type safety and developer productivity.

Leave details and I will get back to you