import { track, trigger } from './effect' import { OperationTypes } from './operations' import { isObject } from '@vue/shared' import { observable } from './index' export const knownValues = new WeakSet() export interface Value { value: T } const convert = (val: any): any => (isObject(val) ? observable(val) : val) export function value(raw: T): Value { raw = convert(raw) const v = { get value() { track(v, OperationTypes.GET, '') return raw }, set value(newVal) { raw = convert(newVal) trigger(v, OperationTypes.SET, '') } } knownValues.add(v) return v } export function isValue(v: any): v is Value { return knownValues.has(v) } type BailTypes = | Function | Map | Set | WeakMap | WeakSet // Recursively unwraps nested value bindings. // Unfortunately TS cannot do recursive types, but this should be enough for // practical use cases... export type UnwrapValue = T extends Value ? UnwrapValue2 : T extends Array ? Array> : T extends BailTypes ? T // bail out on types that shouldn't be unwrapped : T extends object ? { [K in keyof T]: UnwrapValue2 } : T type UnwrapValue2 = T extends Value ? UnwrapValue3 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue3 } : T type UnwrapValue3 = T extends Value ? UnwrapValue4 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue4 } : T type UnwrapValue4 = T extends Value ? UnwrapValue5 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue5 } : T type UnwrapValue5 = T extends Value ? UnwrapValue6 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue6 } : T type UnwrapValue6 = T extends Value ? UnwrapValue7 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue7 } : T type UnwrapValue7 = T extends Value ? UnwrapValue8 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue8 } : T type UnwrapValue8 = T extends Value ? UnwrapValue9 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue9 } : T type UnwrapValue9 = T extends Value ? UnwrapValue10 : T extends Array ? Array> : T extends BailTypes ? T : T extends object ? { [K in keyof T]: UnwrapValue10 } : T type UnwrapValue10 = T extends Value ? V // stop recursion : T