Skip to content

Commit 21dc081

Browse files
committed
fix nested object in mapped type is not partial in update operation
1 parent f805c20 commit 21dc081

File tree

3 files changed

+78
-34
lines changed

3 files changed

+78
-34
lines changed

src/abc.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {
2+
getFirelord,
3+
MetaTypeCreator,
4+
getFirestore,
5+
query,
6+
orderBy,
7+
where,
8+
} from './index'
9+
10+
type A = MetaTypeCreator<{ a: number; b: string }, 'A'>
11+
12+
const a = getFirelord<A>(getFirestore(), 'A')
13+
14+
const q1 = query(a.collection(), where('a', '==', 1), orderBy('b'))
15+
16+
const q2 = query(a.collection(), orderBy('b'), where('a', '==', 1))

src/tests/discriminatedUnion.test.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ type DU = MetaTypeCreator<
1111
| { a: { b: 1; c: 2 } | { b: 'a'; d: 'b' } }
1212
| { x: { y: 1; z: 2; u: 3 } | { y: 'a'; w: 'b'; v: 'c' } | false }
1313
| { c: false }
14-
| { c: true; v: 0 },
14+
| { c: true; v: 0 }
15+
| Record<string, { k: Record<`${1 | 2 | 3}`, number> }>,
1516
'abc'
1617
>
1718

@@ -73,9 +74,17 @@ describe('test discrimination unions', () => {
7374
v: 'c',
7475
},
7576
}
76-
// should be error because no const assertion but ok
77+
// should be error because no const assertion, not an ok behavior but expected
7778
// @ts-expect-error
7879
updateDoc(docRef, data)
80+
81+
updateDoc(docRef, { random: { k: { '1': 1, '2': 2 } } })
82+
83+
const a = { m: '1' as '1' | '2' | '3' }
84+
85+
const b = a.m
86+
87+
updateDoc(docRef, { random: { k: { [b]: 1 } } })
7988
}
8089
})
8190

src/types/exactOptional.ts

+51-32
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,54 @@ type ExactOptionalArray<T, Data> = T extends (infer ElementOfBase)[]
6363
: HandleUnknownMember<T, Data>
6464
: T
6565

66+
type ExceptOptionalSub<
67+
T extends Record<string, unknown>,
68+
K,
69+
Data,
70+
Merge extends boolean | string[], // this is for set merge operation only
71+
NoFlatten extends boolean,
72+
TopLevel extends boolean
73+
> = DeepValue<T, K & string> extends infer S
74+
? unknown extends S
75+
? ErrorKeyNotExist<K & string>
76+
: S[] extends (infer BaseKeyElement)[][] | ArrayUnionOrRemove<unknown>[]
77+
? Data[K & keyof Data] extends (infer DataKeyElement)[]
78+
? Data[K & keyof Data] extends never[] // https://stackoverflow.com/questions/71193522/typescript-inferred-never-is-not-never
79+
? DeepPartialExceptArray<S>
80+
: DataKeyElement extends BaseKeyElement
81+
? ExactOptionalArray<BaseKeyElement, DataKeyElement>[]
82+
: BaseKeyElement[]
83+
: IsSetDeleteAbleFieldValueValid<
84+
S,
85+
Data[K & keyof Data],
86+
K & string,
87+
Merge
88+
>
89+
: S extends Record<string, unknown>
90+
? Data[K & keyof Data] extends infer R
91+
? R extends Record<string, unknown>
92+
? ExactOptional<S, R, Merge, NoFlatten, false>
93+
: DeepPartialExceptArray<S>
94+
: never
95+
: Data[K & keyof Data] extends Delete
96+
? NoFlatten extends true
97+
? TopLevel extends false
98+
? ErrorNonTopLevelDeleteField
99+
: IsSetDeleteAbleFieldValueValid<
100+
S,
101+
Data[K & keyof Data],
102+
K & string,
103+
Merge
104+
>
105+
: IsSetDeleteAbleFieldValueValid<
106+
S,
107+
Data[K & keyof Data],
108+
K & string,
109+
Merge
110+
>
111+
: IsSetDeleteAbleFieldValueValid<S, Data[K & keyof Data], K & string, Merge>
112+
: T[K & keyof T]
113+
66114
// type checking for non-array in update operation
67115
export type ExactOptional<
68116
T extends Record<string, unknown>,
@@ -84,38 +132,9 @@ export type ExactOptional<
84132
: keyof Data extends (string extends keyof T ? string | number : keyof T)
85133
? {
86134
[K in keyof T]?: K extends keyof Data
87-
? DeepValue<T, K & string> extends infer S
88-
? unknown extends S
89-
? ErrorKeyNotExist<K & string>
90-
: S[] extends
91-
| (infer BaseKeyElement)[][]
92-
| ArrayUnionOrRemove<unknown>[]
93-
? Data[K] extends (infer DataKeyElement)[]
94-
? Data[K] extends never[] // https://stackoverflow.com/questions/71193522/typescript-inferred-never-is-not-never
95-
? DeepPartialExceptArray<S>
96-
: DataKeyElement extends BaseKeyElement
97-
? ExactOptionalArray<BaseKeyElement, DataKeyElement>[]
98-
: BaseKeyElement[]
99-
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
100-
: S extends Record<string, unknown>
101-
? Data[K] extends infer R
102-
? R extends Record<string, unknown>
103-
? ExactOptional<S, R, Merge, NoFlatten, false>
104-
: DeepPartialExceptArray<S>
105-
: never
106-
: Data[K] extends Delete
107-
? NoFlatten extends true
108-
? TopLevel extends false
109-
? ErrorNonTopLevelDeleteField
110-
: IsSetDeleteAbleFieldValueValid<
111-
S,
112-
Data[K],
113-
K & string,
114-
Merge
115-
>
116-
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
117-
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
118-
: T[K]
135+
? ExceptOptionalSub<T, K, Data, Merge, NoFlatten, TopLevel>
136+
: string extends K
137+
? ExceptOptionalSub<T, K, Data, Merge, NoFlatten, TopLevel>
119138
: T[K]
120139
}
121140
: HandleUnknownMember<DeepPartialExceptArray<T>, Data>

0 commit comments

Comments
 (0)