types: improve value unwrapping

This commit is contained in:
Evan You
2019-05-30 13:35:50 +08:00
parent 6441db45c7
commit b82b7af29b
5 changed files with 114 additions and 72 deletions

View File

@@ -73,7 +73,7 @@ export function cleanup(effect: ReactiveEffect) {
for (let i = 0; i < effect.deps.length; i++) {
effect.deps[i].delete(effect)
}
effect.deps = []
effect.deps.length = 0
}
export function track(

View File

@@ -24,13 +24,13 @@ import {
DebuggerEvent
} from './effect'
import { UnwrapValues } from './value'
import { UnwrapValue } from './value'
export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
export { OperationTypes } from './operations'
export { computed, ComputedValue } from './computed'
export { lock, unlock } from './lock'
export { value, isValue, Value, UnwrapValues } from './value'
export { value, isValue, Value, UnwrapValue } from './value'
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
@@ -44,7 +44,7 @@ const canObserve = (value: any): boolean => {
)
}
type ObservableFactory = <T>(target?: T) => UnwrapValues<T>
type ObservableFactory = <T>(target?: T) => UnwrapValue<T>
export const observable = ((target: any = {}): any => {
// if trying to observe an immutable proxy, return the immutable version.

View File

@@ -31,58 +31,88 @@ export function isValue(v: any): v is Value<any> {
return knownValues.has(v)
}
type UnwrapValue<T, U = T> = T extends Value<infer V> ? V : T extends {} ? U : T
type BailTypes =
| Function
| Map<any, any>
| Set<any>
| WeakMap<any, any>
| WeakSet<any>
// A utility type that recursively unwraps value bindings nested inside an
// observable object. Unfortunately TS cannot do recursive types, but this
// should be enough for practical use cases...
export type UnwrapValues<T> = {
[key in keyof T]: UnwrapValue<
T[key],
{
[k2 in keyof T[key]]: UnwrapValue<
T[key][k2],
{
[k3 in keyof T[key][k2]]: UnwrapValue<
T[key][k2][k3],
{
[k4 in keyof T[key][k2][k3]]: UnwrapValue<
T[key][k2][k3][k4],
{
[k5 in keyof T[key][k2][k3][k4]]: UnwrapValue<
T[key][k2][k3][k4][k5],
{
[k6 in keyof T[key][k2][k3][k4][k5]]: UnwrapValue<
T[key][k2][k3][k4][k5][k6],
{
[k7 in keyof T[key][k2][k3][k4][k5][k6]]: UnwrapValue<
T[key][k2][k3][k4][k5][k6][k7],
{
[k8 in keyof T[key][k2][k3][k4][k5][k6][k7]]: UnwrapValue<
T[key][k2][k3][k4][k5][k6][k7][k8],
{
[k9 in keyof T[key][k2][k3][k4][k5][k6][k7][k8]]: UnwrapValue<
T[key][k2][k3][k4][k5][k6][k7][k8][k9],
{
[k10 in keyof T[key][k2][k3][k4][k5][k6][k7][k8][k9]]: UnwrapValue<
T[key][k2][k3][k4][k5][k6][k7][k8][k9][k10]
>
}
>
}
>
}
>
}
>
}
>
}
>
}
>
}
>
}
>
}
// Recursively unwraps nested value bindings.
// Unfortunately TS cannot do recursive types, but this should be enough for
// practical use cases...
export type UnwrapValue<T> = T extends Value<infer V>
? UnwrapValue2<V>
: T extends Array<infer V>
? Array<UnwrapValue2<V>>
: T extends BailTypes
? T // bail out on types that shouldn't be unwrapped
: T extends object ? { [K in keyof T]: UnwrapValue2<T[K]> } : T
type UnwrapValue2<T> = T extends Value<infer V>
? UnwrapValue3<V>
: T extends Array<infer V>
? Array<UnwrapValue3<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue3<T[K]> } : T
type UnwrapValue3<T> = T extends Value<infer V>
? UnwrapValue4<V>
: T extends Array<infer V>
? Array<UnwrapValue4<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue4<T[K]> } : T
type UnwrapValue4<T> = T extends Value<infer V>
? UnwrapValue5<V>
: T extends Array<infer V>
? Array<UnwrapValue5<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue5<T[K]> } : T
type UnwrapValue5<T> = T extends Value<infer V>
? UnwrapValue6<V>
: T extends Array<infer V>
? Array<UnwrapValue6<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue6<T[K]> } : T
type UnwrapValue6<T> = T extends Value<infer V>
? UnwrapValue7<V>
: T extends Array<infer V>
? Array<UnwrapValue7<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue7<T[K]> } : T
type UnwrapValue7<T> = T extends Value<infer V>
? UnwrapValue8<V>
: T extends Array<infer V>
? Array<UnwrapValue8<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue8<T[K]> } : T
type UnwrapValue8<T> = T extends Value<infer V>
? UnwrapValue9<V>
: T extends Array<infer V>
? Array<UnwrapValue9<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue9<T[K]> } : T
type UnwrapValue9<T> = T extends Value<infer V>
? UnwrapValue10<V>
: T extends Array<infer V>
? Array<UnwrapValue10<V>>
: T extends BailTypes
? T
: T extends object ? { [K in keyof T]: UnwrapValue10<T[K]> } : T
type UnwrapValue10<T> = T extends Value<infer V>
? V // stop recursion
: T