--- category: Reactivity related: syncRefs --- # syncRef Two-way refs synchronization. ## Usage ```ts import { syncRef } from '@vueuse/core' const a = ref('a') const b = ref('b') const stop = syncRef(a, b) console.log(a.value) // a b.value = 'foo' console.log(a.value) // foo a.value = 'bar' console.log(b.value) // bar ``` ### One directional ```ts import { syncRef } from '@vueuse/core' const a = ref('a') const b = ref('b') const stop = syncRef(a, b, { direction: 'rtl' }) ``` ### Custom Transform ```ts import { syncRef } from '@vueuse/core' const a = ref(10) const b = ref(2) const stop = syncRef(a, b, { transform: { ltr: left => left * 2, rtl: right => right / 2 } }) console.log(b.value) // 20 b.value = 30 console.log(a.value) // 15 ``` ## Type Declarations ```ts type Direction = "ltr" | "rtl" | "both" type SpecificFieldPartial = Partial> & Omit /** * A = B */ type Equal = [A] extends [B] ? ([B] extends [A] ? true : false) : false /** * A ∩ B ≠ ∅ */ type IntersectButNotEqual = Equal extends true ? false : A & B extends never ? false : true /** * A ⊆ B */ type IncludeButNotEqual = Equal extends true ? false : A extends B ? true : false /** * A ∩ B = ∅ */ type NotIntersect = Equal extends true ? false : A & B extends never ? true : false interface EqualType< D extends Direction, L, R, O extends keyof Transform = D extends "both" ? "ltr" | "rtl" : D, > { transform?: SpecificFieldPartial, O>, O> } type StrictIncludeMap< IncludeType extends "LR" | "RL", D extends Exclude, L, R, > = Equal<[IncludeType, D], ["LR", "ltr"]> & Equal<[IncludeType, D], ["RL", "rtl"]> extends true ? { transform?: SpecificFieldPartial, D>, D> } : { transform: Pick, D> } type StrictIncludeType< IncludeType extends "LR" | "RL", D extends Direction, L, R, > = D extends "both" ? { transform: SpecificFieldPartial< Transform, IncludeType extends "LR" ? "ltr" : "rtl" > } : D extends Exclude ? StrictIncludeMap : never type IntersectButNotEqualType = D extends "both" ? { transform: Transform } : D extends Exclude ? { transform: Pick, D> } : never type NotIntersectType = IntersectButNotEqualType< D, L, R > interface Transform { ltr: (left: L) => R rtl: (right: R) => L } type TransformType = Equal extends true ? EqualType : IncludeButNotEqual extends true ? StrictIncludeType<"LR", D, L, R> : IncludeButNotEqual extends true ? StrictIncludeType<"RL", D, L, R> : IntersectButNotEqual extends true ? IntersectButNotEqualType : NotIntersect extends true ? NotIntersectType : never export type SyncRefOptions< L, R, D extends Direction, > = ConfigurableFlushSync & { /** * Watch deeply * * @default false */ deep?: boolean /** * Sync values immediately * * @default true */ immediate?: boolean /** * Direction of syncing. Value will be redefined if you define syncConvertors * * @default 'both' */ direction?: D } & TransformType /** * Two-way refs synchronization. * From the set theory perspective to restrict the option's type * Check in the following order: * 1. L = R * 2. L ∩ R ≠ ∅ * 3. L ⊆ R * 4. L ∩ R = ∅ */ export declare function syncRef( left: Ref, right: Ref, ...[options]: Equal extends true ? [options?: SyncRefOptions] : [options: SyncRefOptions] ): () => void ```