diff --git a/packages/runtime-core/__tests__/apiCreateApp.spec.ts b/packages/runtime-core/__tests__/apiCreateApp.spec.ts index f6386339741..be61dd39b6a 100644 --- a/packages/runtime-core/__tests__/apiCreateApp.spec.ts +++ b/packages/runtime-core/__tests__/apiCreateApp.spec.ts @@ -1,5 +1,7 @@ import { + type InjectionKey, type Plugin, + type Ref, createApp, defineComponent, getCurrentInstance, @@ -111,7 +113,28 @@ describe('api: createApp', () => { app2.provide('bar', 2) expect(`App already provides property with key "bar".`).toHaveBeenWarned() }) - + test('app.provide should be safe type', () => { + type Cube = { + size: number + } + const injectionKeyRef: InjectionKey> = Symbol('key') + const Root = { + setup() { + return () => h(Child) + }, + } + const Child = { + setup() { + const foo = inject(injectionKeyRef) + return () => `${foo?.value.size}` + }, + } + const app = createApp(Root) + app.provide(injectionKeyRef, ref({ size: 10 })) + const root = nodeOps.createElement('div') + app.mount(root) + expect(serializeInner(root)).toBe(`10`) + }) test('runWithContext', () => { const app = createApp({ setup() { diff --git a/packages/runtime-core/src/apiCreateApp.ts b/packages/runtime-core/src/apiCreateApp.ts index 65c10166de7..3d6f8586dd0 100644 --- a/packages/runtime-core/src/apiCreateApp.ts +++ b/packages/runtime-core/src/apiCreateApp.ts @@ -17,7 +17,7 @@ import type { } from './componentPublicInstance' import { type Directive, validateDirectiveName } from './directives' import type { ElementNamespace, RootRenderFunction } from './renderer' -import type { InjectionKey } from './apiInject' +import type { Provide } from './apiInject' import { warn } from './warning' import { type VNode, cloneVNode, createVNode } from './vnode' import type { RootHydrateFunction } from './hydration' @@ -50,7 +50,7 @@ export interface App { namespace?: boolean | ElementNamespace, ): ComponentPublicInstance unmount(): void - provide(key: InjectionKey | string, value: T): this + provide: Provide /** * Runs a function with the app as active instance. This allows using of `inject()` within the function to get access diff --git a/packages/runtime-core/src/apiInject.ts b/packages/runtime-core/src/apiInject.ts index f15983604bb..fa0a39f926c 100644 --- a/packages/runtime-core/src/apiInject.ts +++ b/packages/runtime-core/src/apiInject.ts @@ -6,10 +6,11 @@ import { warn } from './warning' export interface InjectionKey extends Symbol {} -export function provide | string | number>( +export type Provide = | string | number>( key: K, value: K extends InjectionKey ? V : T, -) { +) => void +export const provide: Provide = (key, value) => { if (!currentInstance) { if (__DEV__) { warn(`provide() can only be used inside setup().`)