diff --git a/src/factories.ts b/src/factories.ts index 657ae1b9..fbbc3eba 100644 --- a/src/factories.ts +++ b/src/factories.ts @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -import { Field, Schema } from './schema.js'; +import { AnonymousField, Field, Schema } from './schema.js'; import * as dtypes from './type.js'; import { Data, DataProps } from './data.js'; import { BuilderType, JavaScriptDataType } from './interfaces.js'; @@ -270,3 +270,16 @@ export function builderThroughAsyncIterable; } + +/** + * Helper factory to create a type-safe anonymous field. + * @param type The type of the field + * @param nullable Whether the field is nullable + * @param metadata Optional metadata for the field + * @returns An anonymous field to be used in a [FieldDictionary]{@link FieldDictionary} + */ +export const anonymousField = ( + type: T, + nullable?: boolean, + metadata?: Map +) => ({ type, nullable, metadata }) as AnonymousField; diff --git a/src/schema.ts b/src/schema.ts index 2eb33b78..ddfb48e9 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -26,11 +26,16 @@ export class Schema { public readonly metadataVersion: MetadataVersion; constructor( - fields: Field[] = [], + fields: Field[] | FieldDictionary = {} as FieldDictionary, metadata?: Map | null, dictionaries?: Map | null, metadataVersion = MetadataVersion.V5) { - this.fields = (fields || []) as Field[]; + if (Array.isArray(fields)) { + this.fields = fields as Field[]; + } else { + const entries = Object.entries(fields); + this.fields = entries.map(([name, field]) => new Field(name, field.type, field.nullable, field.metadata)); + } this.metadata = metadata || new Map(); if (!dictionaries) { dictionaries = generateDictionaryMap(this.fields); @@ -177,3 +182,13 @@ function generateDictionaryMap(fields: Field[], dictionaries = new Map = { + readonly type: T; + readonly nullable?: boolean; + readonly metadata?: Map; +} + +export type FieldDictionary = { + [name in keyof T]: AnonymousField; +}