diff --git a/packages/reactivity/src/index.ts b/packages/reactivity/src/index.ts index bdfa64f6..1c9cf821 100644 --- a/packages/reactivity/src/index.ts +++ b/packages/reactivity/src/index.ts @@ -9,7 +9,8 @@ export { triggerRef, Ref, UnwrapRef, - ToRefs + ToRefs, + RefUnwrapBailTypes } from './ref' export { reactive, diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 470cd41f..07a5fc85 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -139,13 +139,37 @@ export function toRef( // corner case when use narrows type // Ex. type RelativePath = string & { __brand: unknown } // RelativePath extends object -> true -type BaseTypes = string | number | boolean | Node | Window +type BaseTypes = string | number | boolean + +/** + * This is a special exported interface for other packages to declare + * additional types that should bail out for ref unwrapping. For example + * \@vue/runtime-dom can declare it like so in its d.ts: + * + * ``` ts + * declare module '@vue/reactivity' { + * export interface RefUnwrapBailTypes { + * runtimeDOMBailTypes: Node | Window + * } + * } + * ``` + * + * Note that api-extractor somehow refuses to include `decalre module` + * augmentations in its generated d.ts, so we have to manually append them + * to the final generated d.ts in our build process. + */ +export interface RefUnwrapBailTypes {} export type UnwrapRef = T extends ComputedRef ? UnwrapRefSimple : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple -type UnwrapRefSimple = T extends Function | CollectionTypes | BaseTypes | Ref +type UnwrapRefSimple = T extends + | Function + | CollectionTypes + | BaseTypes + | Ref + | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] ? T : T extends Array ? T : T extends object ? UnwrappedObject : T diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index a7049f17..96822e84 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -87,6 +87,23 @@ export { // Types ----------------------------------------------------------------------- +import { VNode } from './vnode' +import { ComponentInternalInstance } from './component' + +// Augment Ref unwrap bail types. +// Note: if updating this, also update `types/refBail.d.ts`. +declare module '@vue/reactivity' { + export interface RefUnwrapBailTypes { + runtimeCoreBailTypes: + | VNode + | { + // directly bailing on ComponentPublicInstance results in recursion + // so we use this as a bail hint + $: ComponentInternalInstance + } + } +} + export { ReactiveEffect, ReactiveEffectOptions, diff --git a/packages/runtime-core/types/refBail.d.ts b/packages/runtime-core/types/refBail.d.ts new file mode 100644 index 00000000..c7ab63de --- /dev/null +++ b/packages/runtime-core/types/refBail.d.ts @@ -0,0 +1,14 @@ +// Note: this file is auto concatenated to the end of the bundled d.ts during +// build. + +declare module '@vue/reactivity' { + export interface RefUnwrapBailTypes { + runtimeCoreBailTypes: + | VNode + | { + // directly bailing on ComponentPublicInstance results in recursion + // so we use this as a bail hint + $: ComponentInternalInstance + } + } +} diff --git a/packages/runtime-dom/package.json b/packages/runtime-dom/package.json index b715e076..3963f083 100644 --- a/packages/runtime-dom/package.json +++ b/packages/runtime-dom/package.json @@ -18,9 +18,6 @@ "esm-browser", "cjs", "global" - ], - "dts": [ - "jsx.d.ts" ] }, "repository": { diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index 03de7f70..693e7dbf 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -14,6 +14,13 @@ import { patchProp } from './patchProp' // Importing from the compiler, will be tree-shaken in prod import { isFunction, isString, isHTMLTag, isSVGTag } from '@vue/shared' +declare module '@vue/reactivity' { + export interface RefUnwrapBailTypes { + // Note: if updating this, also update `types/refBail.d.ts`. + runtimeDOMBailTypes: Node | Window + } +} + const rendererOptions = { patchProp, ...nodeOps diff --git a/packages/runtime-dom/jsx.d.ts b/packages/runtime-dom/types/jsx.d.ts similarity index 99% rename from packages/runtime-dom/jsx.d.ts rename to packages/runtime-dom/types/jsx.d.ts index 8748c4f6..8e7ed1cd 100644 --- a/packages/runtime-dom/jsx.d.ts +++ b/packages/runtime-dom/types/jsx.d.ts @@ -1,3 +1,6 @@ +// Note: this file is auto concatenated to the end of the bundled d.ts during +// build. + import { Ref, ComponentPublicInstance } from '@vue/runtime-core' // This code is based on react definition in DefinitelyTyped published under the MIT license. diff --git a/packages/runtime-dom/types/refBail.d.ts b/packages/runtime-dom/types/refBail.d.ts new file mode 100644 index 00000000..549b0ec3 --- /dev/null +++ b/packages/runtime-dom/types/refBail.d.ts @@ -0,0 +1,8 @@ +// Note: this file is auto concatenated to the end of the bundled d.ts during +// build. + +declare module '@vue/reactivity' { + export interface RefUnwrapBailTypes { + runtimeDOMBailTypes: Node | Window + } +} diff --git a/scripts/build.js b/scripts/build.js index 3550f137..32d091ee 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -107,13 +107,15 @@ async function build(target) { }) if (extractorResult.succeeded) { - // concat additional d.ts to rolled-up dts (mostly for JSX) - if (pkg.buildOptions && pkg.buildOptions.dts) { + // concat additional d.ts to rolled-up dts + const typesDir = path.resolve(pkgDir, 'types') + if (await fs.exists(typesDir)) { const dtsPath = path.resolve(pkgDir, pkg.types) const existing = await fs.readFile(dtsPath, 'utf-8') + const typeFiles = await fs.readdir(typesDir) const toAdd = await Promise.all( - pkg.buildOptions.dts.map(file => { - return fs.readFile(path.resolve(pkgDir, file), 'utf-8') + typeFiles.map(file => { + return fs.readFile(path.resolve(typesDir, file), 'utf-8') }) ) await fs.writeFile(dtsPath, existing + '\n' + toAdd.join('\n')) diff --git a/tsconfig.json b/tsconfig.json index ade912a1..42a85205 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,13 +19,14 @@ "rootDir": ".", "paths": { "@vue/*": ["packages/*/src"], - "vue": ["packages/vue/src"] + "vue": ["packages/vue/src"], + "@vue/reavitity": ["packages/reactivity/src/index.ts"] } }, "include": [ "packages/global.d.ts", - "packages/runtime-dom/jsx.d.ts", "packages/*/src", + "packages/runtime-dom/types/jsx.d.ts", "packages/*/__tests__", "test-dts" ]