From 14f1814292c8586802e4d1c6484a115e4000ce0f Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 10:10:30 +0000 Subject: [PATCH 1/7] types: improve type error logging and nest ref types --- packages/reactivity/src/ref.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index e2ff79e1..3c3159ce 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -84,18 +84,20 @@ function toProxyRef( type UnwrapArray = { [P in keyof T]: UnwrapRef } -// Recursively unwraps nested value bindings. -export type UnwrapRef = { - cRef: T extends ComputedRef ? UnwrapRef : T - ref: T extends Ref ? UnwrapRef : T - array: T extends Array ? Array> & UnwrapArray : T - object: { [K in keyof T]: UnwrapRef } -}[T extends ComputedRef - ? 'cRef' - : T extends Ref - ? 'ref' - : T extends Array - ? 'array' - : T extends Function | CollectionTypes - ? 'ref' // bail out on types that shouldn't be unwrapped - : T extends object ? 'object' : 'ref'] +type UnwrapProp = T extends ComputedRef + ? UnwrapRef + : T extends Ref + ? UnwrapRef + : T extends Function | CollectionTypes + ? T + : T extends object + ? UnwrapObject + : T extends Array ? Array> & UnwrapArray : T + +type UnwrapObject = { [K in keyof T]: UnwrapProp } + +export type UnwrapRef = T extends object + ? UnwrapObject + : T extends Function | CollectionTypes + ? T + : T extends Array ? Array> & UnwrapArray : T From 07ff08956ffc45eeba6a4df071b448c585b5ad6d Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 14:09:52 +0000 Subject: [PATCH 2/7] chore: simplifying and improve tupple & array output type on ref --- packages/reactivity/src/ref.ts | 37 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 3c3159ce..b6df32a2 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -82,22 +82,27 @@ function toProxyRef( } as any } -type UnwrapArray = { [P in keyof T]: UnwrapRef } +// Super simple tuple checker +type Tupple> = T[0] extends T[1] + ? T[1] extends T[2] ? never : true + : true -type UnwrapProp = T extends ComputedRef - ? UnwrapRef - : T extends Ref - ? UnwrapRef - : T extends Function | CollectionTypes - ? T - : T extends object - ? UnwrapObject - : T extends Array ? Array> & UnwrapArray : T +export type UnwrapRef = T extends ComputedRef + ? UnwrapRefSimple + : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple -type UnwrapObject = { [K in keyof T]: UnwrapProp } +type UnwrapRefSimple = T extends Function | CollectionTypes + ? T + : T extends Array + ? Tupple extends never ? UnwrappedArray : UnwrapTupple + : T extends object ? UnwrappedObject : T -export type UnwrapRef = T extends object - ? UnwrapObject - : T extends Function | CollectionTypes - ? T - : T extends Array ? Array> & UnwrapArray : T +export type UnwrapTupple = { [P in keyof T]: UnwrapRef } & { + length: number + [Symbol.iterator]: any + [Symbol.unscopables]: any +} + +interface UnwrappedArray extends Array> {} + +type UnwrappedObject = { [P in keyof T]: UnwrapRef } From 9edc4fa1fe54d36edd7208d54eef2ed23da1ad6c Mon Sep 17 00:00:00 2001 From: pikax Date: Sat, 4 Jan 2020 14:22:09 +0000 Subject: [PATCH 3/7] types: fix failed typings? --- packages/runtime-core/__tests__/apiTemplateRef.spec.ts | 3 +-- packages/runtime-core/src/apiWatch.ts | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts index d164d457..f9b6b1b5 100644 --- a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts @@ -4,7 +4,6 @@ import { h, render, nextTick, - Ref, createComponent } from '@vue/runtime-test' @@ -142,7 +141,7 @@ describe('api: template refs', () => { foo: ref(null), bar: ref(null) } - const refKey: Ref = ref('foo') + const refKey = ref('foo') const Comp = { setup() { diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index efd3dfd4..a3fd6acf 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -72,7 +72,10 @@ export function watch( // Readonly constraint helps the callback to correctly infer value types based // on position in the source array. Otherwise the values will get a union type // of all possible value types. -export function watch[]>>( +export function watch< + T extends Readonly>, + TArgs extends Array = any[] +>( sources: T, cb: WatchHandler>, options?: WatchOptions From ab9add4f781e5c0f517afa4ad5d5331ac1f3af8f Mon Sep 17 00:00:00 2001 From: pikax Date: Wed, 8 Apr 2020 21:33:06 +0100 Subject: [PATCH 4/7] types: bring back my changes --- packages/reactivity/src/ref.ts | 37 ++++++++++++------- .../__tests__/apiTemplateRef.spec.ts | 1 - 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 3b334538..485f5646 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -103,16 +103,27 @@ function toProxyRef( // RelativePath extends object -> true type BaseTypes = string | number | boolean -// Recursively unwraps nested value bindings. -export type UnwrapRef = { - cRef: T extends ComputedRef ? UnwrapRef : T - ref: T extends Ref ? UnwrapRef : T - array: T - object: { [K in keyof T]: UnwrapRef } -}[T extends ComputedRef - ? 'cRef' - : T extends Array - ? '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[0] extends T[1] + ? T[1] extends T[2] ? never : true + : true + +export type UnwrapRef = T extends ComputedRef + ? UnwrapRefSimple + : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple + +type UnwrapRefSimple = T extends Function | CollectionTypes | BaseTypes | Ref + ? T + : T extends Array + ? Tupple extends never ? Array : UnwrapTupple + : T extends object ? UnwrappedObject : T + +export type UnwrapTupple = { [P in keyof T]: T[P] } & { + length: number + [Symbol.iterator]: any + [Symbol.unscopables]: any +} + +// interface UnwrappedArray extends Array {} + +type UnwrappedObject = { [P in keyof T]: UnwrapRef } diff --git a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts index 1ba8526a..acf4f5b3 100644 --- a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts @@ -4,7 +4,6 @@ import { h, render, nextTick, - Ref, defineComponent, reactive } from '@vue/runtime-test' From c20d8af8c089bc2c9a47f8a551bff659bb69c6c9 Mon Sep 17 00:00:00 2001 From: pikax Date: Sun, 12 Apr 2020 11:25:46 +0100 Subject: [PATCH 5/7] types: add symbolExtract to extract all known symbols #951 --- packages/reactivity/src/ref.ts | 41 +++++++++++++++++++++++++++++++--- test-dts/ref.test-d.ts | 11 ++++++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 485f5646..f129de67 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -112,7 +112,12 @@ export type UnwrapRef = T extends ComputedRef ? UnwrapRefSimple : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple -type UnwrapRefSimple = T extends Function | CollectionTypes | BaseTypes | Ref +type UnwrapRefSimple = T extends + | Function + | CollectionTypes + | BaseTypes + | Ref + | Element ? T : T extends Array ? Tupple extends never ? Array : UnwrapTupple @@ -124,6 +129,36 @@ export type UnwrapTupple = { [P in keyof T]: T[P] } & { [Symbol.unscopables]: any } -// interface UnwrappedArray extends Array {} +// 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 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 = { [P in keyof T]: UnwrapRef } +type UnwrappedObject = { [P in keyof T]: UnwrapRef } & SymbolExtract diff --git a/test-dts/ref.test-d.ts b/test-dts/ref.test-d.ts index d4f07253..e0a70d64 100644 --- a/test-dts/ref.test-d.ts +++ b/test-dts/ref.test-d.ts @@ -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) { // ref coercing @@ -20,6 +20,15 @@ function foo(arg: number | Ref) { }) expectType>(nestedRef) expectType<{ foo: number }>(nestedRef.value) + + interface IteratorFoo { + [Symbol.iterator]: any + } + expectType> | Ref>( + ref(null) + ) + + expectType | Ref>(ref(null)) } foo(1) From 70b55d797f2f1f6db8c7047ac30207cfc98bf58f Mon Sep 17 00:00:00 2001 From: Carlos Rodrigues Date: Wed, 15 Apr 2020 16:07:07 +0100 Subject: [PATCH 6/7] Apply suggestions from code review Co-Authored-By: Evan You --- packages/reactivity/src/ref.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 2eef093e..569e4e0d 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -129,7 +129,7 @@ export function toRef( type BaseTypes = string | number | boolean | Node | Window // Super simple tuple checker -type Tupple> = T[0] extends T[1] +type IsTuple> = T[0] extends T[1] ? T[1] extends T[2] ? never : true : true @@ -145,10 +145,10 @@ type UnwrapRefSimple = T extends | Element ? T : T extends Array - ? Tupple extends never ? Array : UnwrapTupple + ? IsTuple extends true ? UnwrapTuple : Array : T extends object ? UnwrappedObject : T -export type UnwrapTupple = { [P in keyof T]: T[P] } & { +export type UnwrapTuple = { [P in keyof T]: T[P] } & { length: number [Symbol.iterator]: any [Symbol.unscopables]: any From 8a74260b70d5e7a8063be9621e9d1a0b88336572 Mon Sep 17 00:00:00 2001 From: pikax Date: Wed, 15 Apr 2020 16:22:44 +0100 Subject: [PATCH 7/7] types: remove tuple check and add type check for tuple --- packages/reactivity/src/ref.ts | 22 ++-------------------- test-dts/ref.test-d.ts | 9 +++++---- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 569e4e0d..d2898673 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -128,31 +128,13 @@ export function toRef( // RelativePath extends object -> true type BaseTypes = string | number | boolean | Node | Window -// Super simple tuple checker -type IsTuple> = T[0] extends T[1] - ? T[1] extends T[2] ? never : true - : true - export type UnwrapRef = T extends ComputedRef ? UnwrapRefSimple : T extends Ref ? UnwrapRefSimple : UnwrapRefSimple -type UnwrapRefSimple = T extends - | Function - | CollectionTypes - | BaseTypes - | Ref - | Element +type UnwrapRefSimple = T extends Function | CollectionTypes | BaseTypes | Ref ? T - : T extends Array - ? IsTuple extends true ? UnwrapTuple : Array - : T extends object ? UnwrappedObject : T - -export type UnwrapTuple = { [P in keyof T]: T[P] } & { - length: number - [Symbol.iterator]: any - [Symbol.unscopables]: any -} + : T extends Array ? T : T extends object ? UnwrappedObject : T // Extract all known symbols from an object // when unwrapping Object the symbols are not `in keyof`, this should cover all the diff --git a/test-dts/ref.test-d.ts b/test-dts/ref.test-d.ts index a2c71748..f9b72312 100644 --- a/test-dts/ref.test-d.ts +++ b/test-dts/ref.test-d.ts @@ -21,14 +21,15 @@ function plainType(arg: number | Ref) { expectType>(nestedRef) expectType<{ foo: number }>(nestedRef.value) + // tuple + expectType<[number, string]>(unref(ref([1, '1']))) + interface IteratorFoo { [Symbol.iterator]: any } - expectType> | Ref>( - ref(null) - ) - expectType | Ref>(ref(null)) + // with symbol + expectType(unref(ref(null))) } plainType(1)