]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types: add symbolExtract to extract all known symbols
authorpikax <carlos@hypermob.co.uk>
Sun, 12 Apr 2020 10:25:46 +0000 (11:25 +0100)
committerpikax <carlos@hypermob.co.uk>
Sun, 12 Apr 2020 10:45:56 +0000 (11:45 +0100)
#951

packages/reactivity/src/ref.ts
test-dts/ref.test-d.ts

index 485f5646271154f30de6132d2634942bcf7a2c8a..f129de67e2c77fca3596a307deb1d6cf86dfdbdc 100644 (file)
@@ -112,7 +112,12 @@ 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
+type UnwrapRefSimple<T> = T extends
+  | Function
+  | CollectionTypes
+  | BaseTypes
+  | Ref
+  | Element
   ? T
   : T extends Array<infer V>
     ? Tupple<T> extends never ? Array<V> : UnwrapTupple<T>
@@ -124,6 +129,36 @@ export type UnwrapTupple<T> = { [P in keyof T]: T[P] } & {
   [Symbol.unscopables]: any
 }
 
-// interface UnwrappedArray<T> extends Array<T> {}
-
-type UnwrappedObject<T> = { [P in keyof T]: UnwrapRef<T[P]> }
+// 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 d4f0725388740bc46f22220ae945430fcd908dcb..e0a70d64f94e0330d9e38e31c30344f68dcae827 100644 (file)
@@ -1,5 +1,5 @@
 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>) {
   // ref coercing
@@ -20,6 +20,15 @@ function foo(arg: number | Ref<number>) {
   })
   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)