]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip(vapor): make createComponent rawProps/rawSlots accept wider types for internal use
authorEvan You <evan@vuejs.org>
Tue, 10 Dec 2024 07:50:49 +0000 (15:50 +0800)
committerEvan You <evan@vuejs.org>
Tue, 10 Dec 2024 07:50:49 +0000 (15:50 +0800)
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/componentProps.ts
packages/runtime-vapor/src/componentSlots.ts

index f544809b7d68166b5c5e749bde77244e6e8f81d4..18fe296e2d39507cf8df647812fffefca71f6f75 100644 (file)
@@ -27,6 +27,7 @@ import { type Block, insert, isBlock, remove } from './block'
 import { pauseTracking, proxyRefs, resetTracking } from '@vue/reactivity'
 import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
 import {
+  type DynamicPropsSource,
   type RawProps,
   getPropsProxyHandlers,
   hasFallthroughAttrs,
@@ -39,6 +40,7 @@ import { emit, normalizeEmitsOptions } from './componentEmits'
 import { setStyle } from './dom/style'
 import { setClass, setDynamicProp } from './dom/prop'
 import {
+  type DynamicSlotSource,
   type RawSlots,
   type Slot,
   type StaticSlots,
@@ -97,10 +99,25 @@ interface SharedInternalOptions {
   __emitsOptions?: ObjectEmitsOptions
 }
 
+// In TypeScript, it is actually impossible to have a record type with only
+// specific properties that have a different type from the indexed type.
+// This makes our rawProps / rawSlots shape difficult to satisfy when calling
+// `createComponent` - luckily this is not user-facing, so we don't need to be
+// 100% strict. Here we use intentionally wider types to make `createComponent`
+// more ergonomic in tests and internal call sites, where we immediately cast
+// them into the stricter types.
+type LooseRawProps = Record<string, (() => unknown) | DynamicPropsSource[]> & {
+  $?: DynamicPropsSource[]
+}
+
+type LooseRawSlots = Record<string, Slot | DynamicSlotSource[]> & {
+  $?: DynamicSlotSource[]
+}
+
 export function createComponent(
   component: VaporComponent,
-  rawProps?: RawProps | null,
-  rawSlots?: RawSlots | null,
+  rawProps?: LooseRawProps | null,
+  rawSlots?: LooseRawSlots | null,
   isSingleRoot?: boolean,
   appContext?: GenericAppContext,
 ): VaporComponentInstance {
@@ -114,7 +131,9 @@ export function createComponent(
   ) {
     const attrs = currentInstance.attrs
     if (rawProps) {
-      ;(rawProps.$ || (rawProps.$ = [])).push(() => attrs)
+      ;((rawProps as RawProps).$ || ((rawProps as RawProps).$ = [])).push(
+        () => attrs,
+      )
     } else {
       rawProps = { $: [() => attrs] } as RawProps
     }
@@ -122,8 +141,8 @@ export function createComponent(
 
   const instance = new VaporComponentInstance(
     component,
-    rawProps,
-    rawSlots,
+    rawProps as RawProps,
+    rawSlots as RawSlots,
     appContext,
   )
 
index 501770674b1ec7bda2b0bbd014f090c57886a247..1e615b578700e81a2065d5db53042d0a68dd9fef 100644 (file)
@@ -28,7 +28,7 @@ export type RawProps = Record<string, () => unknown> & {
   $?: DynamicPropsSource[]
 }
 
-type DynamicPropsSource =
+export type DynamicPropsSource =
   | (() => Record<string, unknown>)
   | Record<string, () => unknown>
 
index d33d76bce9e3281982aa8a01ae1c8dbf6e6cda4f..4ee38284026ffc128a1695109806f34ada182c83 100644 (file)
@@ -10,7 +10,7 @@ import type { VaporComponentInstance } from './component'
 import { renderEffect } from './renderEffect'
 
 export type RawSlots = Record<string, Slot> & {
-  $?: (StaticSlots | DynamicSlotFn)[]
+  $?: DynamicSlotSource[]
 }
 
 export type StaticSlots = Record<string, Slot>
@@ -18,6 +18,7 @@ export type StaticSlots = Record<string, Slot>
 export type Slot = BlockFn
 export type DynamicSlot = { name: string; fn: Slot }
 export type DynamicSlotFn = () => DynamicSlot | DynamicSlot[]
+export type DynamicSlotSource = StaticSlots | DynamicSlotFn
 
 export const dynamicSlotsProxyHandlers: ProxyHandler<RawSlots> = {
   get: getSlot,