]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
Merge remote-tracking branch 'github/master' into changing_unwrap_ref
authorpikax <carlos@hypermob.co.uk>
Mon, 13 Apr 2020 17:32:14 +0000 (18:32 +0100)
committerpikax <carlos@hypermob.co.uk>
Mon, 13 Apr 2020 17:32:14 +0000 (18:32 +0100)
1  2 
packages/reactivity/src/ref.ts
test-dts/ref.test-d.ts

index f129de67e2c77fca3596a307deb1d6cf86dfdbdc,05304ad7ef90384bfc954c840d7a869d6fd67fc7..479b5847b8164c348e9761c8bb57fa6a02773f74
@@@ -101,64 -101,18 +101,64 @@@ function toProxyRef<T extends object, 
  // corner case when use narrows type
  // Ex. type RelativePath = string & { __brand: unknown }
  // RelativePath extends object -> true
- type BaseTypes = string | number | boolean
+ type BaseTypes = string | number | boolean | Node | Window
  
 -// Recursively unwraps nested value bindings.
 -export type UnwrapRef<T> = {
 -  cRef: T extends ComputedRef<infer V> ? UnwrapRef<V> : T
 -  ref: T extends Ref<infer V> ? UnwrapRef<V> : T
 -  array: T
 -  object: { [K in keyof T]: UnwrapRef<T[K]> }
 -}[T extends ComputedRef<any>
 -  ? 'cRef'
 -  : T extends Array<any>
 -    ? 'array'
 -    : T extends Ref | Function | CollectionTypes | BaseTypes
 -      ? 'ref' // bail out on types that shouldn't be unwrapped
 -      : T extends object ? 'object' : 'ref']
 +// Super simple tuple checker
 +type Tupple<T extends Array<any>> = T[0] extends T[1]
 +  ? T[1] extends T[2] ? never : true
 +  : true
 +
 +export type UnwrapRef<T> = T extends ComputedRef<infer V>
 +  ? UnwrapRefSimple<V>
 +  : T extends Ref<infer V> ? UnwrapRefSimple<V> : UnwrapRefSimple<T>
 +
 +type UnwrapRefSimple<T> = T extends
 +  | Function
 +  | CollectionTypes
 +  | BaseTypes
 +  | Ref
 +  | Element
 +  ? T
 +  : T extends Array<infer V>
 +    ? Tupple<T> extends never ? Array<V> : UnwrapTupple<T>
 +    : T extends object ? UnwrappedObject<T> : T
 +
 +export type UnwrapTupple<T> = { [P in keyof T]: T[P] } & {
 +  length: number
 +  [Symbol.iterator]: any
 +  [Symbol.unscopables]: any
 +}
 +
 +// Extract all known symbols from an object
 +// when unwrapping Object the symbols are not `in keyof`, this should cover all the
 +// known symbols
 +type SymbolExtract<T> = (T extends { [Symbol.asyncIterator]: infer V }
 +  ? { [Symbol.asyncIterator]: V }
 +  : {}) &
 +  (T extends { [Symbol.hasInstance]: infer V }
 +    ? { [Symbol.hasInstance]: V }
 +    : {}) &
 +  (T extends { [Symbol.isConcatSpreadable]: infer V }
 +    ? { [Symbol.isConcatSpreadable]: V }
 +    : {}) &
 +  (T extends { [Symbol.iterator]: infer V } ? { [Symbol.iterator]: V } : {}) &
 +  (T extends { [Symbol.match]: infer V } ? { [Symbol.match]: V } : {}) &
 +  (T extends { [Symbol.matchAll]: infer V } ? { [Symbol.matchAll]: V } : {}) &
 +  (T extends { [Symbol.observable]: infer V }
 +    ? { [Symbol.observable]: V }
 +    : {}) &
 +  (T extends { [Symbol.replace]: infer V } ? { [Symbol.replace]: V } : {}) &
 +  (T extends { [Symbol.search]: infer V } ? { [Symbol.search]: V } : {}) &
 +  (T extends { [Symbol.species]: infer V } ? { [Symbol.species]: V } : {}) &
 +  (T extends { [Symbol.split]: infer V } ? { [Symbol.split]: V } : {}) &
 +  (T extends { [Symbol.toPrimitive]: infer V }
 +    ? { [Symbol.toPrimitive]: V }
 +    : {}) &
 +  (T extends { [Symbol.toStringTag]: infer V }
 +    ? { [Symbol.toStringTag]: V }
 +    : {}) &
 +  (T extends { [Symbol.unscopables]: infer V }
 +    ? { [Symbol.unscopables]: V }
 +    : {})
 +
 +type UnwrappedObject<T> = { [P in keyof T]: UnwrapRef<T[P]> } & SymbolExtract<T>
index e0a70d64f94e0330d9e38e31c30344f68dcae827,4f862a0686dbc6b9227ca0f4cac01a0a209e82f8..a2c717483bdc5bf8b3763095a6cb3793c84742d7
@@@ -1,7 -1,7 +1,7 @@@
  import { expectType } from 'tsd'
 -import { Ref, ref, isRef, unref } from './index'
 +import { Ref, ref, isRef, unref, UnwrapRef } from './index'
  
- function foo(arg: number | Ref<number>) {
+ function plainType(arg: number | Ref<number>) {
    // ref coercing
    const coerced = ref(arg)
    expectType<Ref<number>>(coerced)
    })
    expectType<Ref<{ foo: number }>>(nestedRef)
    expectType<{ foo: number }>(nestedRef.value)
 +
 +  interface IteratorFoo {
 +    [Symbol.iterator]: any
 +  }
 +  expectType<Ref<UnwrapRef<IteratorFoo>> | Ref<null>>(
 +    ref<IteratorFoo | null>(null)
 +  )
 +
 +  expectType<Ref<HTMLElement> | Ref<null>>(ref<HTMLElement | null>(null))
  }
  
- foo(1)
+ plainType(1)
+ function bailType(arg: HTMLElement | Ref<HTMLElement>) {
+   // ref coercing
+   const coerced = ref(arg)
+   expectType<Ref<HTMLElement>>(coerced)
+   // isRef as type guard
+   if (isRef(arg)) {
+     expectType<Ref<HTMLElement>>(arg)
+   }
+   // ref unwrapping
+   expectType<HTMLElement>(unref(arg))
+   // ref inner type should be unwrapped
+   const nestedRef = ref({ foo: ref(document.createElement('DIV')) })
+   expectType<Ref<{ foo: HTMLElement }>>(nestedRef)
+   expectType<{ foo: HTMLElement }>(nestedRef.value)
+ }
+ const el = document.createElement('DIV')
+ bailType(el)