在 TypeScript 中編寫 Stories
在 TypeScript 中編寫 story 能提升您的生產力。您不必在檔案之間跳轉來查找元件的 props。您的程式碼編輯器會提醒您缺少必要的 props,甚至自動完成 prop 值,就像在您的應用程式中使用元件一樣。此外,Storybook 會推斷這些元件類型以自動生成「控制項」表格。
Storybook 內建 TypeScript 支援,因此您可以零配置開始使用。
使用 Meta
和 StoryObj
為 stories 定義類型
在編寫 stories 時,有兩個方面有助於定義類型。第一個是元件 meta,它描述和配置元件及其 stories。在 CSF 檔案中,這是預設導出。第二個是 stories 本身。
Storybook 為這些都提供了實用類型,分別名為 Meta
和 StoryObj
。這是一個使用這些類型的 CSF 檔案範例
// Replace your-renderer with the renderer you are using (e.g., react, vue3, etc.)
import type { Meta, StoryObj } from '@storybook/your-renderer';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Basic: Story = {};
export const Primary: Story = {
args: {
primary: true,
},
};
Props 類型參數
Meta
和 StoryObj
類型都是泛型,因此您可以為它們提供一個可選的 prop 類型參數,用於元件類型或元件的 props 類型(例如,Meta<typeof Button>
中的 typeof Button
部分)。這樣做,TypeScript 將阻止您定義無效的 arg,並且所有的裝飾器、play 函數或載入器都將為它們的函數參數定義類型。
上面的範例傳遞了元件類型。請參閱定義自訂 args 類型章節,以查看傳遞 props 類型的範例。
使用 satisfies
獲得更好的類型安全
如果您使用 TypeScript 4.9+,您可以利用新的 satisfies
運算符來獲得更嚴格的類型檢查。現在,您將收到缺少必要 args 的類型錯誤,而不僅僅是無效的 args。
使用 satisfies
來應用 story 的類型有助於在跨 stories 共享 play 函數時保持類型安全。如果沒有它,TypeScript 會拋出錯誤,指出 play 函數可能未定義。satisfies
運算符使 TypeScript 能夠推斷 play 函數是否已定義。
最後,使用 satisfies
允許您將 typeof meta
傳遞給 StoryObj
泛型。這會通知 TypeScript meta 和 StoryObj
類型之間的關聯,從而使其能夠從 meta 類型推斷 args 類型。換句話說,TypeScript 將理解 args 可以在 story 和 meta 層級定義,並且當必要的 arg 在 meta 層級定義,但不在 story 層級定義時,不會拋出錯誤。
定義自訂 args 類型
有時,stories 需要定義不包含在元件 props 中的 args。對於這種情況,您可以使用交集類型來組合元件的 props 類型和您的自訂 args 類型。例如,以下是如何使用 footer
arg 來填充子元件
import type { Meta, StoryObj } from '@storybook/react';
import { Page } from './Page';
type PagePropsAndCustomArgs = React.ComponentProps<typeof Page> & { footer?: string };
const meta: Meta<PagePropsAndCustomArgs> = {
component: Page,
render: ({ footer, ...args }) => (
<Page {...args}>
<footer>{footer}</footer>
</Page>
),
};
export default meta;
type Story = StoryObj<PagePropsAndCustomArgs>;
export const CustomFooter: Story = {
args: {
footer: 'Built with Storybook',
},
};