types(reactivity): Simplify the SymbolExtract (#4162)

This commit is contained in:
Pick 2021-07-28 23:12:46 +08:00 committed by GitHub
parent d2585e13e9
commit b79e4ca717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 44 deletions

View File

@ -152,16 +152,44 @@ describe('reactivity/ref', () => {
it('should keep symbols', () => { it('should keep symbols', () => {
const customSymbol = Symbol() const customSymbol = Symbol()
const obj = { const obj = {
[Symbol.asyncIterator]: { a: 1 }, [Symbol.asyncIterator]: ref(1),
[Symbol.unscopables]: { b: '1' }, [Symbol.hasInstance]: { a: ref('a') },
[customSymbol]: { c: [1, 2, 3] } [Symbol.isConcatSpreadable]: { b: ref(true) },
[Symbol.iterator]: [ref(1)],
[Symbol.match]: new Set<Ref<number>>(),
[Symbol.matchAll]: new Map<number, Ref<string>>(),
[Symbol.replace]: { arr: [ref('a')] },
[Symbol.search]: { set: new Set<Ref<number>>() },
[Symbol.species]: { map: new Map<number, Ref<string>>() },
[Symbol.split]: new WeakSet<Ref<boolean>>(),
[Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),
[Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },
[Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },
[customSymbol]: { arr: [ref(1)] }
} }
const objRef = ref(obj) const objRef = ref(obj)
expect(objRef.value[Symbol.asyncIterator]).toBe(obj[Symbol.asyncIterator]) const keys: (keyof typeof obj)[] = [
expect(objRef.value[Symbol.unscopables]).toBe(obj[Symbol.unscopables]) Symbol.asyncIterator,
expect(objRef.value[customSymbol]).toStrictEqual(obj[customSymbol]) Symbol.hasInstance,
Symbol.isConcatSpreadable,
Symbol.iterator,
Symbol.match,
Symbol.matchAll,
Symbol.replace,
Symbol.search,
Symbol.species,
Symbol.split,
Symbol.toPrimitive,
Symbol.toStringTag,
Symbol.unscopables,
customSymbol
]
keys.forEach(key => {
expect(objRef.value[key]).toStrictEqual(obj[key])
})
}) })
test('unref', () => { test('unref', () => {

View File

@ -274,36 +274,7 @@ type UnwrapRefSimple<T> = T extends
: T extends Array<any> : T extends Array<any>
? { [K in keyof T]: UnwrapRefSimple<T[K]> } ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
: T extends object : T extends object
? UnwrappedObject<T> ? {
[P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
}
: T : T
// 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.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>

View File

@ -101,16 +101,42 @@ bailType(el)
function withSymbol() { function withSymbol() {
const customSymbol = Symbol() const customSymbol = Symbol()
const obj = { const obj = {
[Symbol.asyncIterator]: { a: 1 }, [Symbol.asyncIterator]: ref(1),
[Symbol.unscopables]: { b: '1' }, [Symbol.hasInstance]: { a: ref('a') },
[customSymbol]: { c: [1, 2, 3] } [Symbol.isConcatSpreadable]: { b: ref(true) },
[Symbol.iterator]: [ref(1)],
[Symbol.match]: new Set<Ref<number>>(),
[Symbol.matchAll]: new Map<number, Ref<string>>(),
[Symbol.replace]: { arr: [ref('a')] },
[Symbol.search]: { set: new Set<Ref<number>>() },
[Symbol.species]: { map: new Map<number, Ref<string>>() },
[Symbol.split]: new WeakSet<Ref<boolean>>(),
[Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),
[Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },
[Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },
[customSymbol]: { arr: [ref(1)] }
} }
const objRef = ref(obj) const objRef = ref(obj)
expectType<{ a: number }>(objRef.value[Symbol.asyncIterator]) expectType<Ref<number>>(objRef.value[Symbol.asyncIterator])
expectType<{ b: string }>(objRef.value[Symbol.unscopables]) expectType<{ a: Ref<string> }>(objRef.value[Symbol.hasInstance])
expectType<{ c: Array<number> }>(objRef.value[customSymbol]) expectType<{ b: Ref<boolean> }>(objRef.value[Symbol.isConcatSpreadable])
expectType<Ref<number>[]>(objRef.value[Symbol.iterator])
expectType<Set<Ref<number>>>(objRef.value[Symbol.match])
expectType<Map<number, Ref<string>>>(objRef.value[Symbol.matchAll])
expectType<{ arr: Ref<string>[] }>(objRef.value[Symbol.replace])
expectType<{ set: Set<Ref<number>> }>(objRef.value[Symbol.search])
expectType<{ map: Map<number, Ref<string>> }>(objRef.value[Symbol.species])
expectType<WeakSet<Ref<boolean>>>(objRef.value[Symbol.split])
expectType<WeakMap<Ref<boolean>, string>>(objRef.value[Symbol.toPrimitive])
expectType<{ weakSet: WeakSet<Ref<boolean>> }>(
objRef.value[Symbol.toStringTag]
)
expectType<{ weakMap: WeakMap<Ref<boolean>, string> }>(
objRef.value[Symbol.unscopables]
)
expectType<{ arr: Ref<number>[] }>(objRef.value[customSymbol])
} }
withSymbol() withSymbol()