Skip to content

Commit

Permalink
fix nested object in mapped type is not partial in update operation
Browse files Browse the repository at this point in the history
  • Loading branch information
tylim88 committed Mar 24, 2024
1 parent 3330cff commit c5c2f35
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 34 deletions.
16 changes: 16 additions & 0 deletions src/abc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {
getFirelord,
MetaTypeCreator,
getFirestore,
query,
orderBy,
where,
} from './index'

type A = MetaTypeCreator<{ a: number; b: string }, 'A'>

const a = getFirelord<A>(getFirestore(), 'A')

const q1 = query(a.collection(), where('a', '==', 1), orderBy('b'))

Check warning on line 14 in src/abc.ts

View workflow job for this annotation

GitHub Actions / build_publish

'q1' is assigned a value but never used. Allowed unused vars must match /^_/u

const q2 = query(a.collection(), orderBy('b'), where('a', '==', 1))

Check warning on line 16 in src/abc.ts

View workflow job for this annotation

GitHub Actions / build_publish

'q2' is assigned a value but never used. Allowed unused vars must match /^_/u
13 changes: 11 additions & 2 deletions src/tests/discriminatedUnion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ type DU = MetaTypeCreator<
| { a: { b: 1; c: 2 } | { b: 'a'; d: 'b' } }
| { x: { y: 1; z: 2; u: 3 } | { y: 'a'; w: 'b'; v: 'c' } | false }
| { c: false }
| { c: true; v: 0 },
| { c: true; v: 0 }
| Record<string, { k: Record<`${1 | 2 | 3}`, number> }>,
'abc'
>

Expand Down Expand Up @@ -73,9 +74,17 @@ describe('test discrimination unions', () => {
v: 'c',
},
}
// should be error because no const assertion but ok
// should be error because no const assertion, not an ok behavior but expected
// @ts-expect-error
updateDoc(docRef, data)

updateDoc(docRef, { random: { k: { '1': 1, '2': 2 } } })

const a = { m: '1' as '1' | '2' | '3' }

const b = a.m

updateDoc(docRef, { random: { k: { [b]: 1 } } })

Check failure on line 87 in src/tests/discriminatedUnion.test.ts

View workflow job for this annotation

GitHub Actions / build_publish

Type '{ [x: string]: number; }' is not assignable to type '{ [x: string]: `Error: The value might be incorrect or '${string}' is an unknown property`; [x: number]: never; }'.
}
})

Expand Down
83 changes: 51 additions & 32 deletions src/types/exactOptional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,54 @@ type ExactOptionalArray<T, Data> = T extends (infer ElementOfBase)[]
: HandleUnknownMember<T, Data>
: T

type ExceptOptionalSub<
T extends Record<string, unknown>,
K,
Data,
Merge extends boolean | string[], // this is for set merge operation only
NoFlatten extends boolean,
TopLevel extends boolean
> = DeepValue<T, K & string> extends infer S
? unknown extends S
? ErrorKeyNotExist<K & string>
: S[] extends (infer BaseKeyElement)[][] | ArrayUnionOrRemove<unknown>[]
? Data[K & keyof Data] extends (infer DataKeyElement)[]
? Data[K & keyof Data] extends never[] // https://stackoverflow.com/questions/71193522/typescript-inferred-never-is-not-never
? DeepPartialExceptArray<S>
: DataKeyElement extends BaseKeyElement
? ExactOptionalArray<BaseKeyElement, DataKeyElement>[]
: BaseKeyElement[]
: IsSetDeleteAbleFieldValueValid<
S,
Data[K & keyof Data],
K & string,
Merge
>
: S extends Record<string, unknown>
? Data[K & keyof Data] extends infer R
? R extends Record<string, unknown>
? ExactOptional<S, R, Merge, NoFlatten, false>
: DeepPartialExceptArray<S>
: never
: Data[K & keyof Data] extends Delete
? NoFlatten extends true
? TopLevel extends false
? ErrorNonTopLevelDeleteField
: IsSetDeleteAbleFieldValueValid<
S,
Data[K & keyof Data],
K & string,
Merge
>
: IsSetDeleteAbleFieldValueValid<
S,
Data[K & keyof Data],
K & string,
Merge
>
: IsSetDeleteAbleFieldValueValid<S, Data[K & keyof Data], K & string, Merge>
: T[K & keyof T]

// type checking for non-array in update operation
export type ExactOptional<
T extends Record<string, unknown>,
Expand All @@ -84,38 +132,9 @@ export type ExactOptional<
: keyof Data extends (string extends keyof T ? string | number : keyof T)
? {
[K in keyof T]?: K extends keyof Data
? DeepValue<T, K & string> extends infer S
? unknown extends S
? ErrorKeyNotExist<K & string>
: S[] extends
| (infer BaseKeyElement)[][]
| ArrayUnionOrRemove<unknown>[]
? Data[K] extends (infer DataKeyElement)[]
? Data[K] extends never[] // https://stackoverflow.com/questions/71193522/typescript-inferred-never-is-not-never
? DeepPartialExceptArray<S>
: DataKeyElement extends BaseKeyElement
? ExactOptionalArray<BaseKeyElement, DataKeyElement>[]
: BaseKeyElement[]
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
: S extends Record<string, unknown>
? Data[K] extends infer R
? R extends Record<string, unknown>
? ExactOptional<S, R, Merge, NoFlatten, false>
: DeepPartialExceptArray<S>
: never
: Data[K] extends Delete
? NoFlatten extends true
? TopLevel extends false
? ErrorNonTopLevelDeleteField
: IsSetDeleteAbleFieldValueValid<
S,
Data[K],
K & string,
Merge
>
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
: IsSetDeleteAbleFieldValueValid<S, Data[K], K & string, Merge>
: T[K]
? ExceptOptionalSub<T, K, Data, Merge, NoFlatten, TopLevel>
: string extends K
? ExceptOptionalSub<T, K, Data, Merge, NoFlatten, TopLevel>
: T[K]
}
: HandleUnknownMember<DeepPartialExceptArray<T>, Data>
Expand Down

0 comments on commit c5c2f35

Please sign in to comment.