From 6c215168af088dd95f0997bf5bc4ed96045e993a Mon Sep 17 00:00:00 2001 From: Christian Meredith Date: Fri, 3 Jan 2025 03:24:58 +1100 Subject: [PATCH] Improving TS Type inference by extending Meteor Check typings to include extra Easy Schema declaration styles --- easy-schema.d.ts | 46 ++++++++++++++++++++++++++++++++++++++------ lib/attach/client.js | 2 +- lib/attach/server.js | 2 +- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/easy-schema.d.ts b/easy-schema.d.ts index d00d463..5a6ad0f 100644 --- a/easy-schema.d.ts +++ b/easy-schema.d.ts @@ -1,5 +1,39 @@ +import { Match } from 'meteor/check'; + export declare const has: unique symbol; +type HasFluentSchema = { + [has]: BaseSchema +}; + +// Object pattern limited to +export type ObjectPattern = { + type: HasFluentSchema +}; + +export type Pattern = + | BaseSchema + | HasFluentSchema + | ObjectPattern + | [Pattern] + // Meteor Check doesn't require Pattern[], because check schemas are ephemeral + // so typescript gives e.g. [String] the strict type of [StringConstructor] + // but a schema declared as a variable does not have this benefit of the doubt + // and is inferred as StringConstructor[] + // Object.freeze or `as const` makes TS complain about mutability... can't win. + | Pattern[] + | {[key: string]: Pattern} + | Match.Pattern; + +export type PatternMatch = + T extends BaseSchema ? U : + T extends HasFluentSchema ? U : + T extends [Pattern] ? PatternMatch[] : + T extends Pattern[] ? PatternMatch[] : + T extends ObjectPattern ? U : + T extends {[key: string]: Pattern} ? {[K in keyof T]: PatternMatch} : + Match.PatternMatch; + // Base Schema class for common behavior declare class BaseSchema { constructor(type: T); @@ -87,10 +121,10 @@ export declare const ObjectID: ObjectIDConstructor; * @param data The data to check * @param schema The schema to match `data` against */ -export declare function check( +export declare function check( data: any, schema: T -): asserts data is Match.PatternMatch; +): asserts data is PatternMatch; /** Matches any value. */ @@ -104,7 +138,7 @@ export declare const Integer: Match.Matcher; */ export declare function Optional( pattern: T -): Matcher | undefined | null>; +): Match.Matcher | undefined | null>; /** * Shapes an object based on a POJO. @@ -155,10 +189,10 @@ export declare const EasySchema: { }; declare module 'meteor/mongo' { - module Mongo { + namespace Mongo { interface Collection { - attachSchema(schema: object): void; - schema?: Match.Pattern; + attachSchema(schema: U): Collection> + schema?: Pattern; } } } diff --git a/lib/attach/client.js b/lib/attach/client.js index ef05623..de0fd31 100644 --- a/lib/attach/client.js +++ b/lib/attach/client.js @@ -10,5 +10,5 @@ import { shape } from '../shape.js'; Mongo.Collection.prototype.attachSchema = function(schema) { /** @type {import('meteor/check').Match.Pattern} */ this.schema = { ...shape({...schema, ...config.base}), '$id': `/${this._name}` }; - return; + return this; }; diff --git a/lib/attach/server.js b/lib/attach/server.js index 56dc949..decc484 100644 --- a/lib/attach/server.js +++ b/lib/attach/server.js @@ -177,7 +177,7 @@ Mongo.Collection.prototype.attachSchema = function(schema) { attachMongoSchema(collection, fullSchema); - return; + return this; } catch (error) { console.error(error) }