feat(types): infer expose type from SetupContext in defineComponent#14693
feat(types): infer expose type from SetupContext in defineComponent#14693zhiyuanzmj wants to merge 6 commits intovuejs:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe changes enhance type inference for exposed properties in Vue components by introducing a new generic parameter to the Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
@vue/compiler-core
@vue/compiler-dom
@vue/compiler-sfc
@vue/compiler-ssr
@vue/reactivity
@vue/runtime-core
@vue/runtime-dom
@vue/server-renderer
@vue/shared
vue
@vue/compat
commit: |
Size ReportBundles
Usages
|
There was a problem hiding this comment.
Pull request overview
This PR updates Vue’s public TypeScript typings so that the type of values passed to ctx.expose() can be carried through SetupContext and (intendedly) inferred into the component instance type produced by defineComponent.
Changes:
- Extend
SetupContextwith a new generic parameter representing the exposed object type, and simplify theexposefunction signature to use it. - Thread a new generic (
B) throughdefineComponent’s setup-function overloads to propagate the exposed/bindings type into the returned instance type. - Add DTS tests asserting that exposed properties can be inferred from
SetupContext(and from a minimal{ expose(...) }context shape).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/runtime-core/src/componentOptions.ts | Changes the setup context type to pass a third SetupContext generic derived from RawBindings. |
| packages/runtime-core/src/component.ts | Adds Exposed generic to SetupContext and updates expose typing to use it. |
| packages/runtime-core/src/apiDefineComponent.ts | Adds B generic to DefineSetupFnComponent and defineComponent overloads to propagate exposed/bindings typing. |
| packages-private/dts-test/defineComponent.test-d.tsx | Adds DTS tests for inferring exposed properties from SetupContext. |
Comments suppressed due to low confidence (1)
packages/runtime-core/src/apiDefineComponent.ts:177
- The second
defineComponentoverload returnsDefineSetupFnComponent<Props, E, S, B>but itssetupsignature still typesctxasSetupContext<E, S>(missing theBargument). This prevents inferring (or even specifying) the exposed/bindings typeBwhen using runtime props options (the 2nd argument) and can makeSetupContext<..., ..., B>annotations fail to match this overload. Update this overload to usectx: SetupContext<E, S, B>to keep the generics consistent and allow the new inference behavior in all overloads.
Props extends Record<string, any>,
E extends EmitsOptions = {},
EE extends string = string,
S extends SlotsType = {},
B extends Record<string, any> = {},
>(
setup: (
props: Props,
ctx: SetupContext<E, S>,
) => RenderFunction | Promise<RenderFunction>,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/runtime-core/src/apiDefineComponent.ts (1)
167-183:⚠️ Potential issue | 🟡 MinorInconsistent
SetupContextusage between overloads.The second overload (lines 167-183) declares the
Bgeneric parameter but usesSetupContext<E, S>on line 176 instead ofSetupContext<E, S, B>. This means exposed types won't be inferred when using object-style props options.Compare with the first overload (lines 150-166) which correctly uses
SetupContext<E, S, B>on line 159.🔧 Proposed fix
export function defineComponent< Props extends Record<string, any>, E extends EmitsOptions = {}, EE extends string = string, S extends SlotsType = {}, B extends Record<string, any> = {}, >( setup: ( props: Props, - ctx: SetupContext<E, S>, + ctx: SetupContext<E, S, B>, ) => RenderFunction | Promise<RenderFunction>, options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & { props?: ComponentObjectPropsOptions<Props> emits?: E | EE[] slots?: S }, ): DefineSetupFnComponent<Props, E, S, B>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/runtime-core/src/apiDefineComponent.ts` around lines 167 - 183, The second overload of defineComponent incorrectly uses SetupContext<E, S> while it declares the B generic, so exposed types won't be inferred for object-style props; update the setup parameter's context type in that overload from SetupContext<E, S> to SetupContext<E, S, B> (keeping the rest of the signature—props?: ComponentObjectPropsOptions<Props>, emits?: E | EE[], slots?: S—and return type DefineSetupFnComponent<Props, E, S, B>—so the B generic is actually propagated to the SetupContext).
🧹 Nitpick comments (1)
packages/runtime-core/src/componentOptions.ts (1)
144-144: Clarify the relationship betweenRawBindingsand exposed types.The third generic parameter to
SetupContextis set toRawBindings & {}. Based on the test cases, the type inference flows from an explicitly typedctxparameter annotation back to the component instance. This works because TypeScript infersRawBindingsfrom thectxparameter's type when the setup function is explicitly typed.However, this creates a semantic coupling where
RawBindings(traditionally the setup return type) also becomes the exposed type. Consider documenting this relationship or adding a comment explaining whyRawBindingsis used here rather than a dedicatedExposedparameter.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/runtime-core/src/componentOptions.ts` at line 144, The current use of RawBindings in the SetupContext third generic (ctx: SetupContext<E, S, RawBindings & {}>) ties the exposed type to the setup return type and may confuse readers; add a concise comment above this signature in componentOptions.ts explaining that RawBindings is intentionally reused here so that TypeScript can infer the exposed type from an explicitly typed ctx parameter (i.e., why we pass RawBindings & {} instead of a separate Exposed generic), and note any implications for type inference and semantic coupling between setup return types and exposed instance types (referencing SetupContext and RawBindings in the comment).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/runtime-core/src/apiDefineComponent.ts`:
- Around line 167-183: The second overload of defineComponent incorrectly uses
SetupContext<E, S> while it declares the B generic, so exposed types won't be
inferred for object-style props; update the setup parameter's context type in
that overload from SetupContext<E, S> to SetupContext<E, S, B> (keeping the rest
of the signature—props?: ComponentObjectPropsOptions<Props>, emits?: E | EE[],
slots?: S—and return type DefineSetupFnComponent<Props, E, S, B>—so the B
generic is actually propagated to the SetupContext).
---
Nitpick comments:
In `@packages/runtime-core/src/componentOptions.ts`:
- Line 144: The current use of RawBindings in the SetupContext third generic
(ctx: SetupContext<E, S, RawBindings & {}>) ties the exposed type to the setup
return type and may confuse readers; add a concise comment above this signature
in componentOptions.ts explaining that RawBindings is intentionally reused here
so that TypeScript can infer the exposed type from an explicitly typed ctx
parameter (i.e., why we pass RawBindings & {} instead of a separate Exposed
generic), and note any implications for type inference and semantic coupling
between setup return types and exposed instance types (referencing SetupContext
and RawBindings in the comment).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1d7383bd-daca-4911-85b0-d5f06262a92d
📒 Files selected for processing (4)
packages-private/dts-test/defineComponent.test-d.tsxpackages/runtime-core/src/apiDefineComponent.tspackages/runtime-core/src/component.tspackages/runtime-core/src/componentOptions.ts
|
/ecosystem-ci run |
|
📝 Ran ecosystem CI: Open
|
Summary by CodeRabbit
Tests
SetupContextImprovements
defineComponent