Skip to content

Vue2: Improve CSF3 types#19603

Merged
kasperpeulen merged 11 commits into
nextfrom
future/CSF3-vue2
Oct 25, 2022
Merged

Vue2: Improve CSF3 types#19603
kasperpeulen merged 11 commits into
nextfrom
future/CSF3-vue2

Conversation

@kasperpeulen
Copy link
Copy Markdown
Member

@kasperpeulen kasperpeulen commented Oct 24, 2022

What I did

This PR provides improved type safety for Vue2 stories (similar to what we changed to React, Svelte and Vue3) but requires vue-tsc instead of tsc (And the Volar VS Code extension for editor support):
https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin

To unlock the full potential of this PR, TS 4.9 is needed, for the new satisfies operator. But, this also improves the types for TS<4.9 users.

Typesafe args

We changed StoryObj and Meta to increase type safety for when the user provides args partially in meta.

Considering a Component like this:

<template>
    <button type="button" class="classes" @click="onClick" :disabled="disabled">{{ label }}</button>
</template>

<script lang="ts">
import Vue from 'vue';
import './button.css';

export default Vue.extend({
    name: 'my-button',

    props: {
        label: {
            type: String,
            required: true,
        },
        disabled: {
            type: Boolean,
            default: false,
        },
    },
    methods: {
        onClick(): void {
            this.$emit('onClick');
        },
    },
});
</script>

It is valid to provide args like this:

import Button from './Button.vue';

// ✅ valid
const meta = {
  component: Button,
  args: { disabled: false },
} satisfies Meta<typeof Button>;

// or const meta = Meta<typeof Button> = { ... } in TS<4.9

export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
  args: { label: 'good' }
};

While it is invalid to forget an arg, in either meta or the story:

// ❌ invalid
const meta = {
  component: Button,
} satisfies Meta<typeof Button>;

export const Basic: Story = {
  args: { label: 'good' }
};

// ❌ invalid
const meta = {
  component: Button,
  args: { label: 'good' }
} satisfies Meta<typeof Button>;

export const Basic: Story = {};

Changed Meta to make sure both a Component, as the Props of the component can be used:

const meta = {
  component: Button,
} satisfies Meta<typeof Button>;

export default meta;

export const meta = {
  component: Button,
} satisfies Meta<{label: string; disabled: boolean} >;

export default meta;

Typesafe decorators/loaders

Decorators now accept a new generic arg argument to be specified:

const withDecorator: DecoratorFn<{ decoratorArg: string }> = (
  Story,
  { args: { decoratorArg } }
) =>
  Vue.extend({
    components: { Story },
    template: `<div>Decorator: ${decoratorArg}<Story/></div>`,
  });

And the type of meta/story will check if this arg is part of the generic type:

type Props = ButtonProps & { decoratorArg: string };

const meta = satisfies<Meta<Props>>()({
  component: Button,
  args: { disabled: false },
  decorators: [withDecorator],
});

type Story = StoryObj<typeof meta>;
const Basic: Story = { args: { decoratorArg: 0, label: 'good' } };

I also fixed some typescript issues in other files in this package.

How to test

You can test it by running: yarn nx run @storybook/vue:check

Copy link
Copy Markdown
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The tests are going to stand us in very good stead!

Copy link
Copy Markdown
Member

@shilman shilman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

Comment thread code/renderers/vue/src/docs/sourceDecorator.ts Outdated
@kasperpeulen kasperpeulen removed the request for review from prashantpalikhe October 25, 2022 12:38
@kasperpeulen kasperpeulen merged commit 065bd82 into next Oct 25, 2022
@kasperpeulen kasperpeulen deleted the future/CSF3-vue2 branch October 25, 2022 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants