diff --git a/types/test/options-test.ts b/types/test/options-test.ts index ec06f9b8252..b1ecf065dc4 100644 --- a/types/test/options-test.ts +++ b/types/test/options-test.ts @@ -281,6 +281,12 @@ Vue.component('provide-function', { }) }) +Vue.component('component-with-slot', { + render (h): VNode { + return h('div', this.$slots.default) + } +}) + Vue.component('component-with-scoped-slot', { render (h) { interface ScopedSlotProps { @@ -301,6 +307,12 @@ Vue.component('component-with-scoped-slot', { h('child', { // Passing down all slots from parent scopedSlots: this.$scopedSlots + }), + h('child', { + // Passing down single slot from parent + scopedSlots: { + default: this.$scopedSlots.default + } }) ]) }, @@ -320,16 +332,22 @@ Vue.component('narrow-array-of-vnode-type', { render (h): VNode { const slot = this.$scopedSlots.default!({}) if (typeof slot === 'string') { + // return h('span', slot) } else if (Array.isArray(slot)) { + // template with multiple children const first = slot[0] - if (!Array.isArray(first) && typeof first !== 'string') { + if (!Array.isArray(first) && typeof first !== 'string' && first) { return first } else { return h() } - } else { + } else if (slot) { + //
bare VNode
return slot + } else { + // empty template, slot === undefined + return h() } } }) diff --git a/types/vnode.d.ts b/types/vnode.d.ts index 6bc41352d02..b32f77926f0 100644 --- a/types/vnode.d.ts +++ b/types/vnode.d.ts @@ -1,9 +1,14 @@ import { Vue } from "./vue"; -export type ScopedSlot = (props: any) => VNodeChildrenArrayContents | VNode | string; +// Scoped slots can technically return anything if used from +// a render function, but this is "good enough" for templates +export type ScopedSlot = (props: any) => ScopedSlotChildren; +export type ScopedSlotChildren = ScopedSlotArrayContents | VNode | string | undefined; +export interface ScopedSlotArrayContents extends Array {} -export type VNodeChildren = VNodeChildrenArrayContents | [ScopedSlot] | string; -export interface VNodeChildrenArrayContents extends Array {} +// Relaxed type compatible with $createElement +export type VNodeChildren = VNodeChildrenArrayContents | [ScopedSlot] | string | boolean | null | undefined; +export interface VNodeChildrenArrayContents extends Array {} export interface VNode { tag?: string; @@ -27,7 +32,7 @@ export interface VNodeComponentOptions { Ctor: typeof Vue; propsData?: object; listeners?: object; - children?: VNodeChildren; + children?: VNode[]; tag?: string; }