Skip to content

Commit a655521

Browse files
committed
fix: functional component & public instance
1 parent 2b70d7f commit a655521

File tree

7 files changed

+45
-23
lines changed

7 files changed

+45
-23
lines changed

packages/compiler-sfc/src/compileScript.ts

+8
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ export function compileScript(
726726
let propsOption = undefined
727727
let emitsOption = undefined
728728
let exposeOption = undefined
729+
let slotsOption = undefined
729730
if (optionsRuntimeDecl.type === 'ObjectExpression') {
730731
for (const prop of optionsRuntimeDecl.properties) {
731732
if (
@@ -735,6 +736,7 @@ export function compileScript(
735736
if (prop.key.name === 'props') propsOption = prop
736737
if (prop.key.name === 'emits') emitsOption = prop
737738
if (prop.key.name === 'expose') exposeOption = prop
739+
if (prop.key.name === 'slots') slotsOption = prop
738740
}
739741
}
740742
}
@@ -757,6 +759,12 @@ export function compileScript(
757759
exposeOption
758760
)
759761
}
762+
if (slotsOption) {
763+
error(
764+
`${DEFINE_OPTIONS}() cannot be used to declare slots. Use ${DEFINE_SLOTS}() instead.`,
765+
slotsOption
766+
)
767+
}
760768

761769
return true
762770
}

packages/dts-test/functionalComponent.test-d.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { h, Text, FunctionalComponent, Component } from 'vue'
1+
import { h, Text, FunctionalComponent, Component, SlotsType, VNode } from 'vue'
22
import { expectType } from './utils'
33

44
// simple function signature
@@ -68,3 +68,12 @@ const Qux: FunctionalComponent<{}, ['foo', 'bar']> = (props, { emit }) => {
6868
}
6969

7070
expectType<Component>(Qux)
71+
72+
const Quux: FunctionalComponent<{}, {}, { default: [foo: number] }> = (
73+
props,
74+
{ emit, slots }
75+
) => {
76+
expectType<{ default: (foo: number) => VNode[] }>(slots)
77+
}
78+
expectType<Component>(Quux)
79+
;<Quux />

packages/runtime-core/src/apiSetupHelpers.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,7 @@ export function defineOptions<
156156
C extends ComputedOptions = {},
157157
M extends MethodOptions = {},
158158
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
159-
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
160-
E extends EmitsOptions = EmitsOptions,
161-
EE extends string = string
159+
Extends extends ComponentOptionsMixin = ComponentOptionsMixin
162160
>(
163161
options?: ComponentOptionsWithoutProps<
164162
{},
@@ -167,10 +165,8 @@ export function defineOptions<
167165
C,
168166
M,
169167
Mixin,
170-
Extends,
171-
E,
172-
EE
173-
> & { emits?: undefined; expose?: undefined }
168+
Extends
169+
> & { emits?: undefined; expose?: undefined; slots?: undefined }
174170
): void {
175171
if (__DEV__) {
176172
warnRuntimeUsage(`defineOptions`)

packages/runtime-core/src/component.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
normalizePropsOptions
2929
} from './componentProps'
3030
import {
31-
Slots,
3231
initSlots,
3332
InternalSlots,
3433
SlotsType,
@@ -126,12 +125,13 @@ export interface ComponentInternalOptions {
126125
export interface FunctionalComponent<
127126
P = {},
128127
E extends EmitsOptions = {},
129-
S extends SlotsType = {}
128+
S extends Record<string, any[]> = {}
130129
> extends ComponentInternalOptions {
131130
// use of any here is intentional so it can be a valid JSX Element constructor
132-
(props: P, ctx: Omit<SetupContext<E, S>, 'expose'>): any
131+
(props: P, ctx: Omit<SetupContext<E, SlotsType<S>>, 'expose'>): any
133132
props?: ComponentPropsOptions<P>
134133
emits?: E | (keyof E)[]
134+
slots?: SlotsType<S>
135135
inheritAttrs?: boolean
136136
displayName?: string
137137
compatConfig?: CompatConfig
@@ -156,7 +156,7 @@ export type ConcreteComponent<
156156
M extends MethodOptions = MethodOptions
157157
> =
158158
| ComponentOptions<Props, RawBindings, D, C, M>
159-
| FunctionalComponent<Props, any>
159+
| FunctionalComponent<Props, any, any>
160160

161161
/**
162162
* A type used in public APIs where a component type is expected.
@@ -183,7 +183,7 @@ export type SetupContext<
183183
> = E extends any
184184
? {
185185
attrs: Data
186-
slots: [keyof S] extends [never] ? Slots : TypedSlots<S>
186+
slots: TypedSlots<S>
187187
emit: EmitFn<E>
188188
expose: (exposed?: Record<string, any>) => void
189189
}

packages/runtime-core/src/componentPublicInstance.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
ComponentInjectOptions
4141
} from './componentOptions'
4242
import { EmitsOptions, EmitFn } from './componentEmits'
43-
import { Slots, SlotsType } from './componentSlots'
43+
import { SlotsType, TypedSlots } from './componentSlots'
4444
import { markAttrsAccessed } from './componentRenderUtils'
4545
import { currentRenderingInstance } from './componentRenderContext'
4646
import { warn } from './warning'
@@ -164,6 +164,7 @@ export type CreateComponentPublicInstance<
164164
PublicC,
165165
PublicM,
166166
E,
167+
S,
167168
PublicProps,
168169
PublicDefaults,
169170
MakeDefaultsOptional,
@@ -180,6 +181,7 @@ export type ComponentPublicInstance<
180181
C extends ComputedOptions = {},
181182
M extends MethodOptions = {},
182183
E extends EmitsOptions = {},
184+
S extends SlotsType = {},
183185
PublicProps = P,
184186
Defaults = {},
185187
MakeDefaultsOptional extends boolean = false,
@@ -195,7 +197,7 @@ export type ComponentPublicInstance<
195197
>
196198
$attrs: Data
197199
$refs: Data
198-
$slots: Slots
200+
$slots: TypedSlots<S>
199201
$root: ComponentPublicInstance | null
200202
$parent: ComponentPublicInstance | null
201203
$emit: EmitFn<E>

packages/runtime-core/src/componentSlots.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,16 @@ export type SlotsType<T extends Record<string, any[]> = Record<string, any[]>> =
3636
{
3737
[SlotSymbol]?: T
3838
}
39-
export type TypedSlots<S extends SlotsType> = Readonly<
40-
Prettify<{
41-
[K in keyof NonNullable<S[typeof SlotSymbol]>]: Slot<
42-
NonNullable<S[typeof SlotSymbol]>[K]
39+
40+
export type TypedSlots<S extends SlotsType> = [keyof S] extends [never]
41+
? Slots
42+
: Readonly<
43+
Prettify<{
44+
[K in keyof NonNullable<S[typeof SlotSymbol]>]: Slot<
45+
NonNullable<S[typeof SlotSymbol]>[K]
46+
>
47+
}>
4348
>
44-
}>
45-
>
4649

4750
export type RawSlots = {
4851
[name: string]: unknown

packages/runtime-core/src/h.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,12 @@ export function h(
120120
): VNode
121121

122122
// functional component
123-
export function h<P, E extends EmitsOptions = {}>(
124-
type: FunctionalComponent<P, E>,
123+
export function h<
124+
P,
125+
E extends EmitsOptions = {},
126+
S extends Record<string, any[]> = {}
127+
>(
128+
type: FunctionalComponent<P, E, S>,
125129
props?: (RawProps & P) | ({} extends P ? null : never),
126130
children?: RawChildren | RawSlots
127131
): VNode

0 commit comments

Comments
 (0)