or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

component-system.mdcustom-elements.mddevelopment-tools.mdindex.mdjsx-support.mdreactivity.mdrendering.mdsfc-compilation.mdssr.mdutilities.md
tile.json

reactivity.mddocs/

Reactivity System

Vue's reactivity system provides fine-grained reactive state management with automatic dependency tracking. Built on ES6 Proxies, it offers superior performance and developer experience compared to Vue 2's Object.defineProperty approach.

Capabilities

Basic Reactivity

Ref

Creates a reactive reference that can hold any value type with automatic unwrapping in templates.

/**
 * Creates a reactive reference to a value
 * @param value - Initial value
 * @returns Reactive reference with .value property
 */
function ref<T>(value: T): Ref<UnwrapRef<T>>;
function ref<T = any>(): Ref<T | undefined>;

interface Ref<T = any> {
  value: T;
}

type UnwrapRef<T> = T extends Ref<infer V> ? UnwrapRef<V> : T;

Usage Examples:

import { ref } from "vue";

// Primitive values
const count = ref(0);
const message = ref("Hello");
const isActive = ref(true);

// Objects and arrays (deeply reactive)
const user = ref({ name: "John", age: 30 });
const items = ref([1, 2, 3]);

// Access/modify values
console.log(count.value); // 0
count.value = 10;
user.value.name = "Jane";

Reactive

Creates a reactive proxy of an object with deep reactivity for nested properties.

/**
 * Creates a reactive proxy of an object
 * @param target - Plain object to make reactive
 * @returns Reactive proxy with all nested properties reactive
 */
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>;

Usage Examples:

import { reactive } from "vue";

// Simple object
const state = reactive({
  count: 0,
  message: "Hello"
});

// Nested objects (deeply reactive)
const user = reactive({
  profile: {
    name: "John",
    settings: {
      theme: "dark"
    }
  }
});

// Direct property access (no .value needed)
state.count++; // Reactive
user.profile.name = "Jane"; // Reactive
user.profile.settings.theme = "light"; // Reactive

Readonly

Creates a readonly proxy that prevents modifications while maintaining reactivity for reading.

/**
 * Creates a readonly proxy of an object or ref
 * @param target - Object to make readonly
 * @returns Readonly proxy that throws on write attempts
 */
function readonly<T>(target: T): DeepReadonly<T>;

Shallow Reactivity

Creates shallow reactive proxies that only track changes to top-level properties.

/**
 * Creates a shallow reactive proxy (only root-level properties are reactive)
 * @param target - Object to make shallow reactive
 * @returns Shallow reactive proxy
 */
function shallowReactive<T extends object>(target: T): T;

/**
 * Creates a shallow ref (only .value is reactive, not nested properties)
 * @param value - Initial value
 * @returns Shallow reactive reference
 */
function shallowRef<T>(value: T): ShallowRef<T>;

/**
 * Creates a shallow readonly proxy
 * @param target - Object to make shallow readonly
 * @returns Shallow readonly proxy
 */
function shallowReadonly<T>(target: T): Readonly<T>;

interface ShallowRef<T = any> {
  value: T;
}

Utility Functions

Value Access and Conversion

/**
 * Gets the underlying value from a ref or returns the value if not a ref
 * @param val - Ref or plain value
 * @returns Underlying value
 */
function unref<T>(val: T | Ref<T>): T;

/**
 * Converts a property of a reactive object to a ref
 * @param object - Reactive object
 * @param key - Property key
 * @returns Ref linked to the property
 */
function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]>;

/**
 * Converts all properties of an object to refs
 * @param object - Object to convert
 * @returns Object with all properties as refs
 */
function toRefs<T extends object>(object: T): ToRefs<T>;

/**
 * Gets the underlying value from ref, computed, or function
 * @param val - Ref, computed, function, or plain value
 * @returns Resolved value
 */
function toValue<T>(val: T | Ref<T> | (() => T)): T;

Type Guards

/**
 * Checks if a value is a ref
 * @param val - Value to check
 * @returns True if value is a ref
 */
function isRef<T>(val: Ref<T> | unknown): val is Ref<T>;

/**
 * Checks if a value is a reactive proxy
 * @param value - Value to check
 * @returns True if value is reactive
 */
function isReactive(value: unknown): boolean;

/**
 * Checks if a value is a readonly proxy
 * @param value - Value to check
 * @returns True if value is readonly
 */
function isReadonly(value: unknown): boolean;

/**
 * Checks if a value is a proxy (reactive or readonly)
 * @param value - Value to check
 * @returns True if value is a proxy
 */
function isProxy(value: unknown): boolean;

/**
 * Checks if a reactive value is shallow
 * @param value - Value to check
 * @returns True if value is shallow reactive
 */
function isShallow(value: unknown): boolean;

Raw Value Access

/**
 * Marks an object to never be made reactive
 * @param value - Object to mark as raw
 * @returns Same object marked as raw
 */
function markRaw<T>(value: T): T;

/**
 * Gets the original object from a reactive proxy
 * @param observed - Reactive proxy
 * @returns Original non-reactive object
 */
function toRaw<T>(observed: T): T;

/**
 * Converts a value to reactive proxy
 * @param value - Value to convert
 * @returns Reactive proxy or original value
 */
function toReactive<T>(value: T): T;

/**
 * Converts a value to readonly proxy
 * @param value - Value to convert
 * @returns Readonly proxy or original value
 */
function toReadonly<T>(value: T): T;

Advanced Reactivity

Custom Refs

Create refs with custom getter/setter logic and dependency tracking.

/**
 * Creates a custom ref with explicit dependency tracking control
 * @param factory - Factory function that returns getter/setter
 * @returns Custom ref instance
 */
function customRef<T>(factory: CustomRefFactory<T>): Ref<T>;

type CustomRefFactory<T> = (
  track: () => void,
  trigger: () => void
) => {
  get: () => T;
  set: (value: T) => void;
};

Usage Example:

import { customRef } from "vue";

function useDebouncedRef(value, delay = 200) {
  let timeout;
  return customRef((track, trigger) => {
    return {
      get() {
        track(); // Track dependency
        return value;
      },
      set(newValue) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          value = newValue;
          trigger(); // Trigger updates
        }, delay);
      }
    };
  });
}

Manual Ref Control

/**
 * Manually triggers updates for a shallow ref
 * @param ref - Shallow ref to trigger
 */
function triggerRef(ref: ShallowRef): void;

/**
 * Creates a proxy that unwraps refs automatically
 * @param objectWithRefs - Object containing refs
 * @returns Proxy that unwraps refs on access
 */
function proxyRefs<T extends object>(objectWithRefs: T): ShallowUnwrapRef<T>;

Computed Properties

Basic Computed

/**
 * Creates a computed ref that reactively computes based on dependencies
 * @param getter - Function that computes the value
 * @returns Readonly computed ref
 */
function computed<T>(getter: () => T): ComputedRef<T>;

/**
 * Creates a writable computed ref with getter and setter
 * @param options - Object with get and set functions
 * @returns Writable computed ref
 */
function computed<T>(options: {
  get: () => T;
  set: (value: T) => void;
}): WritableComputedRef<T>;

interface ComputedRef<T = any> extends WritableComputedRef<T> {
  readonly value: T;
}

interface WritableComputedRef<T> extends Ref<T> {
  readonly effect: ReactiveEffect<T>;
}

Usage Examples:

import { ref, computed } from "vue";

const count = ref(0);

// Read-only computed
const doubled = computed(() => count.value * 2);

// Writable computed
const fullName = computed({
  get() {
    return `${firstName.value} ${lastName.value}`;
  },
  set(newValue) {
    [firstName.value, lastName.value] = newValue.split(" ");
  }
});

Effects System

Reactive Effects

/**
 * Creates a reactive effect that runs when dependencies change
 * @param fn - Effect function
 * @param options - Effect options
 * @returns ReactiveEffect instance
 */
function effect<T = any>(
  fn: () => T,
  options?: ReactiveEffectOptions
): ReactiveEffect<T>;

/**
 * Stops a reactive effect
 * @param effect - Effect to stop
 */
function stop(effect: ReactiveEffect): void;

interface ReactiveEffectOptions {
  lazy?: boolean;
  scheduler?: (job: EffectScheduler) => void;
  scope?: EffectScope;
  allowRecurse?: boolean;
  onStop?: () => void;
}

class ReactiveEffect<T = any> {
  constructor(
    public fn: () => T,
    public scheduler: EffectScheduler | null = null,
    scope?: EffectScope
  );
  run(): T;
  stop(): void;
}

Effect Utilities

/**
 * Gets the currently running watcher/effect
 * @returns Current watcher instance or null
 */
function getCurrentWatcher(): ReactiveEffect | null;

/**
 * Registers a cleanup callback for the current watcher
 * @param cleanupFn - Function to call on cleanup
 */
function onWatcherCleanup(cleanupFn: () => void): void;

/**
 * Registers a cleanup callback for the current effect
 * @param cleanupFn - Function to call on cleanup
 */
function onEffectCleanup(cleanupFn: () => void): void;

/**
 * Enable reactivity tracking globally
 */
function enableTracking(): void;

/**
 * Pause reactivity tracking temporarily
 */
function pauseTracking(): void;

/**
 * Reset tracking state to previous level
 */
function resetTracking(): void;

Effect Scope

Collect and manage multiple effects for batch disposal.

/**
 * Creates a new effect scope
 * @param detached - Whether scope is detached from parent
 * @returns EffectScope instance
 */
function effectScope(detached?: boolean): EffectScope;

/**
 * Gets the current active effect scope
 * @returns Current scope or undefined
 */
function getCurrentScope(): EffectScope | undefined;

/**
 * Registers a disposal callback for current scope
 * @param fn - Disposal callback
 */
function onScopeDispose(fn: () => void): void;

class EffectScope {
  run<T>(fn: () => T): T | undefined;
  stop(): void;
}

Usage Example:

import { effectScope, ref, computed } from "vue";

const scope = effectScope();

scope.run(() => {
  const count = ref(0);
  const doubled = computed(() => count.value * 2);
  
  // Effects are collected in scope
});

// Stop all effects in scope
scope.stop();

Type Definitions

type Ref<T = any> = {
  value: T;
  [RefSymbol]: true;
};

type ShallowRef<T = any> = {
  value: T;
  [RefSymbol]: true;
  [ShallowRefMarker]: true;
};

type ComputedRef<T = any> = {
  readonly value: T;
  [RefSymbol]: true;
} & ComputedRefImpl<T>;

type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRefSimple<T>;

type ToRef<T> = T extends Ref ? T : Ref<T>;

type ToRefs<T = any> = {
  [K in keyof T]: ToRef<T[K]>;
};

type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};