diff --git a/packages/effect-firebase/src/lib/firestore/query/query.ts b/packages/effect-firebase/src/lib/firestore/query/query.ts index 1470d26..77758aa 100644 --- a/packages/effect-firebase/src/lib/firestore/query/query.ts +++ b/packages/effect-firebase/src/lib/firestore/query/query.ts @@ -19,23 +19,50 @@ import { // ============================================================================ /** - * Extract field keys from a Schema struct (Model). + * Extract field keys from a Schema struct (Model), including nested fields as dot notation strings. + * + * For example, given a schema: + * ```ts + * const PostSchema = Schema.Struct({ + * title: Schema.String, + * author: Schema.Struct({ + * name: Schema.String, + * age: Schema.Number + * }) + * }); + * + * type PostSchema = Schema.Schema.Type + * type Keys = FieldKeys // "title" | "author.name" | "author.age" + ``` */ -export type FieldKeys = S extends { readonly fields: infer F } - ? keyof F & string - : never; +type DotPrefix = T extends '' ? '' : `.${T}` +export type FieldKeys = ( + S extends object ? + { [K in Exclude]: `${K}${DotPrefix>}` }[Exclude] + : '') extends infer D ? Extract : never /** - * Extract the type of a specific field from a Schema. + * Extract the type of a specific field from a Schema, including nested fields. + * + * For example, + * `FieldType` would be `string`. + * `FieldType` TypeError. + * `FieldType` would be `string`. + * `FieldType` would be `number`. */ -export type FieldType = S extends { +export type FieldType> = S extends { readonly Type: infer T; } - ? K extends keyof T - ? T[K] - : never + ? FieldType + : K extends `${infer Head}.${infer Tail}` + ? Head extends keyof S + ? FieldType> + : never + : K extends keyof S + ? S[K] : never; + // ============================================================================ // Query Builder Type // ============================================================================