Skip to content

feat(component-meta): expose runtime values of enum members in schema - #6131

Merged
KazariEX merged 3 commits into
vuejs:masterfrom
valentinpalkovic:feat/component-meta-enum-literal-values
Jul 24, 2026
Merged

KazariEX merged 3 commits into
vuejs:masterfrom
valentinpalkovic:feat/component-meta-enum-literal-values

Conversation

@valentinpalkovic

@valentinpalkovic valentinpalkovic commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

TS enum members currently resolve to their qualified name only ("MyEnum.Small"), because resolveSchema falls through to typeToString. The runtime value is lost, even though the type checker has it at that exact spot (subtype.value on the literal type).

Consumers cannot recover the values without running their own type checker over the user's project. For docs tooling this matters: Storybook, for example, generates a select control from enum schemas, and with only the member names available it either injects the literal string "MyEnum.Small" into the component (wrong value) or has to drop the control entirely (storybookjs/storybook#35565).

This PR adds a literal schema node for enum member types:

// enum MyStringEnum { Small = 'small', ... }  →  prop: MyStringEnum
{
  kind: 'enum',
  type: 'MyStringEnum',
  schema: [
    { kind: 'literal', type: 'MyStringEnum.Small', value: '"small"' },
    { kind: 'literal', type: 'MyStringEnum.Medium', value: '"medium"' },
    { kind: 'literal', type: 'MyStringEnum.Large', value: '"large"' },
  ],
}
  • value is printed like literal-union members already are: strings quoted, numbers bare.
  • Scoped to TypeFlags.EnumLiteral literal types only: Plain literal unions ('a' | 'b') keep their existing string form, so existing consumers are unaffected there.
  • PropertyMetaSchema gains one variant: { kind: 'literal'; type: string; value: string }.
  • Tests: string enum added to the reference-type-props fixture with a new assertion; the numeric enum snapshot and the tsc dts snapshot are updated accordingly.

Comment thread packages/component-meta/lib/schemaResolvers.ts Outdated
Co-authored-by: Amulet Kerria <85992002+KazariEX@users.noreply.github.com>
@KazariEX
KazariEX merged commit 00ce7ec into vuejs:master Jul 24, 2026
4 checks passed
@KazariEX KazariEX mentioned this pull request Jul 31, 2026
pull Bot pushed a commit to Ballalhossaintalukder/storybook that referenced this pull request Jul 31, 2026
vue-component-meta stringifies a TS enum member to its qualified name
("Severity.Info"), which says nothing about what gets passed to the
component. storybookjs#35565 therefore had to keep enums out of Controls entirely:
an enum sbType would have made a select inject the literal string
"Severity.Info" instead of 'info'.

vuejs/language-tools#6131, released in vue-component-meta 3.3.9, adds a
"literal" schema node carrying the runtime value next to the member name.
Consume it: TS enums now resolve to an enum sbType of their runtime values,
with control.labels mapping each value back to the member name it is
written as. Picking "Severity.Info" in the dropdown passes 'info'; numeric
enums pass 0 and 1. table.type.summary keeps the enum name either way.

The dotted-string guard stays, narrowed to what it actually catches now:
unresolved qualified type names like "typeof Config.alpha", which
stringify with a dot but stand for no value.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants