Moved attributes and adjustments to typed schemas
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Mongo } from 'meteor/mongo';
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import ColorSchema from '/imports/api/properties/subSchemas/ColorSchema';
|
||||
import ChildSchema, { TreeDoc } from '/imports/api/parenting/ChildSchema';
|
||||
import ChildSchema from '/imports/api/parenting/ChildSchema';
|
||||
import SoftRemovableSchema from '/imports/api/parenting/SoftRemovableSchema';
|
||||
import propertySchemasIndex from '/imports/api/properties/computedPropertySchemasIndex';
|
||||
import { storedIconsSchema } from '/imports/api/icons/Icons';
|
||||
@@ -130,17 +130,6 @@ const DenormalisedOnlyCreaturePropertySchema = new TypedSimpleSchema({
|
||||
|
||||
const CreaturePropertySchema = PreComputeCreaturePropertySchema.extend(DenormalisedOnlyCreaturePropertySchema);
|
||||
|
||||
type CreaturePropertyByType<T extends keyof typeof propertySchemasIndex> =
|
||||
InferType<typeof propertySchemasIndex[T]>
|
||||
& InferType<typeof CreaturePropertySchema>
|
||||
& InferType<typeof ColorSchema>
|
||||
& InferType<typeof ChildSchema>
|
||||
& InferType<typeof SoftRemovableSchema>
|
||||
|
||||
type ConvertToUnion<T> = T[keyof T];
|
||||
type CreatureProperty = ConvertToUnion<{ [key in keyof typeof propertySchemasIndex]: CreaturePropertyByType<key> }>;
|
||||
type ActionProperty = CreaturePropertyByType<'action'>;
|
||||
|
||||
const CreatureProperties = new Mongo.Collection<CreatureProperty>('creatureProperties');
|
||||
|
||||
let key: keyof typeof propertySchemasIndex;
|
||||
@@ -164,6 +153,16 @@ for (key in propertySchemasIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
export type CreaturePropertyByType<T extends keyof typeof propertySchemasIndex> =
|
||||
InferType<typeof propertySchemasIndex[T]>
|
||||
& InferType<typeof CreaturePropertySchema>
|
||||
& InferType<typeof ColorSchema>
|
||||
& InferType<typeof ChildSchema>
|
||||
& InferType<typeof SoftRemovableSchema>
|
||||
|
||||
type ConvertToUnion<T> = T[keyof T];
|
||||
export type CreatureProperty = ConvertToUnion<{ [key in keyof typeof propertySchemasIndex]: CreaturePropertyByType<key> }>;
|
||||
|
||||
export default CreatureProperties;
|
||||
export {
|
||||
DenormalisedOnlyCreaturePropertySchema,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import { TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
export interface Reference {
|
||||
collection: string,
|
||||
@@ -15,7 +16,7 @@ export interface TreeDoc {
|
||||
removed?: true,
|
||||
}
|
||||
|
||||
const RefSchema = new SimpleSchema({
|
||||
const RefSchema = new TypedSimpleSchema({
|
||||
id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
@@ -26,7 +27,7 @@ const RefSchema = new SimpleSchema({
|
||||
},
|
||||
});
|
||||
|
||||
const ChildSchema = new SimpleSchema({
|
||||
const ChildSchema = new TypedSimpleSchema({
|
||||
root: {
|
||||
type: Object,
|
||||
},
|
||||
@@ -47,7 +48,7 @@ const ChildSchema = new SimpleSchema({
|
||||
optional: true,
|
||||
},
|
||||
/**
|
||||
* The tree structure goes as follows where the numbering follows a counterclockwise depth first
|
||||
* The tree structure goes as follows where the numbering follows a counter-clockwise depth first
|
||||
* path around the tree. The canonical structure comes from the root and parentId references,
|
||||
* while the left and right numbering is used to optimize ancestor queries.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
let SoftRemovableSchema = new SimpleSchema({
|
||||
let SoftRemovableSchema = new TypedSimpleSchema({
|
||||
'removed': {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
|
||||
@@ -3,64 +3,7 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope
|
||||
import { storedIconsSchema } from '/imports/api/icons/Icons';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX';
|
||||
import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { InlineCalculation } from '/imports/api/properties/subSchemas/inlineCalculationField';
|
||||
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
||||
import Property from '/imports/api/properties/Properties.type';
|
||||
import { TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
export type CreatureAction = Action & CreatureProperty & {
|
||||
overridden?: boolean
|
||||
insufficientResources?: boolean
|
||||
}
|
||||
|
||||
/*
|
||||
* Actions are things a character can do
|
||||
*/
|
||||
export interface Action extends ActionBase {
|
||||
type: 'action'
|
||||
}
|
||||
|
||||
/**
|
||||
* Base property type for both spells and actions
|
||||
*/
|
||||
export interface ActionBase extends Property {
|
||||
name?: string
|
||||
summary?: InlineCalculation
|
||||
description?: InlineCalculation
|
||||
actionType: 'action' | 'bonus' | 'attack' | 'reaction' | 'free' | 'long' | 'event'
|
||||
variableName?: string
|
||||
target: 'self' | 'singleTarget' | 'multipleTargets'
|
||||
attackRoll?: CalculatedField
|
||||
uses?: CalculatedField
|
||||
usesUsed?: number
|
||||
reset?: string
|
||||
silent?: boolean
|
||||
usesLeft?: number
|
||||
// Resources
|
||||
resources: {
|
||||
itemsConsumed: {
|
||||
_id: string
|
||||
tag?: string
|
||||
itemName?: string
|
||||
quantity?: CalculatedField
|
||||
itemId?: string
|
||||
available?: number
|
||||
}[]
|
||||
attributesConsumed: {
|
||||
_id: string
|
||||
variableName?: string
|
||||
quantity?: CalculatedField
|
||||
available?: number
|
||||
statName?: string
|
||||
}[]
|
||||
conditions?: {
|
||||
_id: string,
|
||||
condition?: CalculatedField
|
||||
conditionNote?: string,
|
||||
}[]
|
||||
}
|
||||
}
|
||||
import { Expand, InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
/*
|
||||
* Actions are things a character can do
|
||||
@@ -72,11 +15,11 @@ const ActionSchema = createPropertySchema({
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
summary: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
type: 'inlineCalculationFieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
type: 'inlineCalculationFieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// What time-resource is used to take the action in combat
|
||||
@@ -102,16 +45,16 @@ const ActionSchema = createPropertySchema({
|
||||
'self',
|
||||
'singleTarget',
|
||||
'multipleTargets',
|
||||
],
|
||||
] as const,
|
||||
},
|
||||
// Some actions have an attack roll
|
||||
attackRoll: {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// Calculation of how many times this action can be used
|
||||
uses: {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// Integer of how many times it has already been used
|
||||
@@ -152,7 +95,7 @@ const ActionSchema = createPropertySchema({
|
||||
optional: true,
|
||||
},
|
||||
'resources.itemsConsumed.$.quantity': {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
'resources.itemsConsumed.$.itemId': {
|
||||
@@ -181,7 +124,7 @@ const ActionSchema = createPropertySchema({
|
||||
max: STORAGE_LIMITS.variableName,
|
||||
},
|
||||
'resources.attributesConsumed.$.quantity': {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
'resources.conditions': {
|
||||
@@ -200,7 +143,7 @@ const ActionSchema = createPropertySchema({
|
||||
}
|
||||
},
|
||||
'resources.conditions.$.condition': {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
'resources.conditions.$.conditionNote': {
|
||||
@@ -217,11 +160,11 @@ const ActionSchema = createPropertySchema({
|
||||
|
||||
const ComputedOnlyActionSchema = createPropertySchema({
|
||||
summary: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
type: 'computedOnlyInlineCalculationField' as const,
|
||||
optional: true,
|
||||
},
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
type: 'computedOnlyInlineCalculationField' as const,
|
||||
optional: true,
|
||||
},
|
||||
// True if the uses left is zero, or any item or attribute consumed is
|
||||
@@ -232,12 +175,12 @@ const ComputedOnlyActionSchema = createPropertySchema({
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
attackRoll: {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
uses: {
|
||||
parseLevel: 'reduce',
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
// Uses - usesUsed
|
||||
@@ -270,7 +213,7 @@ const ComputedOnlyActionSchema = createPropertySchema({
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
'resources.itemsConsumed.$.quantity': {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
'resources.itemsConsumed.$.itemName': {
|
||||
@@ -299,7 +242,7 @@ const ComputedOnlyActionSchema = createPropertySchema({
|
||||
type: Object,
|
||||
},
|
||||
'resources.attributesConsumed.$.quantity': {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
'resources.attributesConsumed.$.available': {
|
||||
@@ -319,4 +262,8 @@ const ComputedActionSchema = new TypedSimpleSchema({})
|
||||
.extend(ActionSchema)
|
||||
.extend(ComputedOnlyActionSchema);
|
||||
|
||||
export type Action = InferType<typeof ActionSchema>;
|
||||
export type ComputedOnlyAction = InferType<typeof ComputedOnlyActionSchema>;
|
||||
export type ComputedAction = Expand<InferType<typeof ActionSchema> & InferType<typeof ComputedOnlyActionSchema>>;
|
||||
|
||||
export { ActionSchema, ComputedOnlyActionSchema, ComputedActionSchema };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema';
|
||||
import { Expand, InferType, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
const AdjustmentSchema = createPropertySchema({
|
||||
// The roll that determines how much to change the attribute
|
||||
// This can be simplified, but should only compute when activated
|
||||
amount: {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
parseLevel: 'compile',
|
||||
optional: true,
|
||||
defaultValue: 1,
|
||||
@@ -40,14 +40,18 @@ const AdjustmentSchema = createPropertySchema({
|
||||
|
||||
const ComputedOnlyAdjustmentSchema = createPropertySchema({
|
||||
amount: {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
parseLevel: 'compile',
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedAdjustmentSchema = new SimpleSchema()
|
||||
const ComputedAdjustmentSchema = new TypedSimpleSchema({})
|
||||
.extend(AdjustmentSchema)
|
||||
.extend(ComputedOnlyAdjustmentSchema);
|
||||
|
||||
export type Adjustment = InferType<typeof AdjustmentSchema>;
|
||||
export type ComputedOnlyAdjustment = InferType<typeof ComputedOnlyAdjustmentSchema>;
|
||||
export type ComputedAdjustment = Expand<InferType<typeof AdjustmentSchema> & InferType<typeof ComputedOnlyAdjustmentSchema>>;
|
||||
|
||||
export { AdjustmentSchema, ComputedAdjustmentSchema, ComputedOnlyAdjustmentSchema };
|
||||
@@ -2,52 +2,7 @@ import SimpleSchema from 'simpl-schema';
|
||||
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema';
|
||||
import { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||
import { CalculatedField } from '/imports/api/properties/subSchemas/computedField';
|
||||
import { InlineCalculation } from '/imports/api/properties/subSchemas/inlineCalculationField';
|
||||
import { ConstantValueType } from '/imports/parser/parseTree/constant';
|
||||
import Property from '/imports/api/properties/Properties.type';
|
||||
|
||||
export type CreatureAttribute = Attribute & CreatureProperty & {
|
||||
total?: ConstantValueType;
|
||||
value?: ConstantValueType;
|
||||
modifier?: number;
|
||||
proficiency?: 0 | 0.49 | 0.5 | 1 | 2;
|
||||
advantage?: -1 | 0 | 1;
|
||||
constitutionMod?: number;
|
||||
hide?: true;
|
||||
overridden?: true;
|
||||
effectIds?: string[];
|
||||
proficiencyIds?: string[];
|
||||
definitions?: { _id: string, type: string, row?: number }[];
|
||||
}
|
||||
|
||||
export interface Attribute extends Property {
|
||||
type: 'attribute';
|
||||
name?: string;
|
||||
variableName?: string;
|
||||
attributeType: 'ability' | 'stat' | 'modifier' | 'hitDice' | 'healthBar' | 'resource' |
|
||||
'spellSlot' | 'utility';
|
||||
hitDiceSize?: 'd1' | 'd2' | 'd4' | 'd6' | 'd8' | 'd10' | 'd12' | 'd20' | 'd100';
|
||||
spellSlotLevel?: CalculatedField;
|
||||
healthBarColorMid?: string;
|
||||
healthBarColorLow?: string;
|
||||
healthBarNoDamage?: true;
|
||||
healthBarNoHealing?: true;
|
||||
healthBarNoDamageOverflow?: true;
|
||||
healthBarNoHealingOverflow?: true;
|
||||
healthBarDamageOrder?: number;
|
||||
healthBarHealingOrder?: number;
|
||||
baseValue?: CalculatedField;
|
||||
description?: InlineCalculation;
|
||||
damage?: number;
|
||||
decimal?: true;
|
||||
ignoreLowerLimit?: true;
|
||||
ignoreUpperLimit?: true;
|
||||
hideWhenTotalZero?: true;
|
||||
hideWhenValueZero?: true;
|
||||
reset?: string;
|
||||
}
|
||||
import { Expand, InferType } from '/imports/api/utility/TypedSimpleSchema';
|
||||
|
||||
/*
|
||||
* Attributes are numbered stats of a character
|
||||
@@ -90,7 +45,7 @@ const AttributeSchema = createPropertySchema({
|
||||
},
|
||||
// For type spellSlot, the level needs to be stored separately
|
||||
spellSlotLevel: {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// For type healthBar midColor, and lowColor can be set separately from the
|
||||
@@ -134,12 +89,12 @@ const AttributeSchema = createPropertySchema({
|
||||
},
|
||||
// The starting value, before effects
|
||||
baseValue: {
|
||||
type: 'fieldToCompute',
|
||||
type: 'fieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// Description of what the attribute is used for
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
type: 'inlineCalculationFieldToCompute' as const,
|
||||
optional: true,
|
||||
},
|
||||
// The damage done to the attribute, should always compute as positive
|
||||
@@ -182,15 +137,15 @@ const AttributeSchema = createPropertySchema({
|
||||
|
||||
const ComputedOnlyAttributeSchema = createPropertySchema({
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
type: 'computedOnlyInlineCalculationField' as const,
|
||||
optional: true,
|
||||
},
|
||||
baseValue: {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
spellSlotLevel: {
|
||||
type: 'computedOnlyField',
|
||||
type: 'computedOnlyField' as const,
|
||||
optional: true,
|
||||
},
|
||||
// The computed value of the attribute
|
||||
@@ -346,4 +301,8 @@ const ComputedAttributeSchema = new SimpleSchema({})
|
||||
.extend(ComputedOnlyAttributeSchema)
|
||||
.extend(AttributeSchema);
|
||||
|
||||
export type Attribute = InferType<typeof AttributeSchema>;
|
||||
export type ComputedOnlyAttribute = InferType<typeof ComputedOnlyAttributeSchema>;
|
||||
export type ComputedAttribute = Expand<InferType<typeof AttributeSchema> & InferType<typeof ComputedOnlyAttributeSchema>>;
|
||||
|
||||
export { AttributeSchema, ComputedOnlyAttributeSchema, ComputedAttributeSchema };
|
||||
|
||||
@@ -4,8 +4,11 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||
import { ConstantValueType } from '/imports/parser/parseTree/constant';
|
||||
|
||||
export interface CalculatedField {
|
||||
export type FieldToCalculate = {
|
||||
calculation?: string;
|
||||
}
|
||||
|
||||
export type CalculatedOnlyField = {
|
||||
value?: ConstantValueType;
|
||||
valueNode: ParseNode;
|
||||
effectIds?: string[];
|
||||
@@ -17,6 +20,8 @@ export interface CalculatedField {
|
||||
errors?: any[];
|
||||
}
|
||||
|
||||
export type CalculatedField = FieldToCalculate & CalculatedOnlyField;
|
||||
|
||||
// Get schemas that apply fields directly so they can be gracefully extended
|
||||
// because {type: Schema} fields can't be extended
|
||||
function fieldToCompute(field) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Definition, TypedSimpleSchema } from '/imports/api/utility/TypedSimpleS
|
||||
// Search through the schema for keys whose type is 'fieldToCompute' etc.
|
||||
// replace the type with Object and attach extend the schema with
|
||||
// the required fields to make the computation work
|
||||
export default function createPropertySchema(definition: Definition) {
|
||||
export default function createPropertySchema<T extends Definition>(definition: T): TypedSimpleSchema<T> {
|
||||
const computationFields = {
|
||||
inlineCalculationFieldToCompute: [],
|
||||
computedOnlyInlineCalculationField: [],
|
||||
|
||||
@@ -3,7 +3,11 @@ import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||
import { CalculatedField } from './computedField';
|
||||
|
||||
export interface InlineCalculation {
|
||||
export type InlineCalculationFieldToCompute = {
|
||||
text?: string,
|
||||
}
|
||||
|
||||
export type ComputedOnlyInlineCalculationField = {
|
||||
text?: string,
|
||||
hash?: number,
|
||||
value?: string,
|
||||
@@ -45,6 +49,7 @@ function computedOnlyInlineCalculationField(field) {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.inlineCalculationField,
|
||||
// @ts-expect-error removeBeforeCompute is an extension of SimpleSchema
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
[`${field}.inlineCalculations`]: {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import SimpleSchema, { SimpleSchemaDefinition } from 'simpl-schema';
|
||||
import type {
|
||||
FieldToCalculate, CalculatedOnlyField
|
||||
} from '/imports/api/properties/subSchemas/computedField';
|
||||
import type {
|
||||
InlineCalculationFieldToCompute, ComputedOnlyInlineCalculationField
|
||||
} from '/imports/api/properties/subSchemas/inlineCalculationField';
|
||||
|
||||
// It DOES NOT support a constructor with multiple schemas.
|
||||
export type Definition = Exclude<SimpleSchemaDefinition, any[]>;
|
||||
@@ -27,7 +33,7 @@ type NotImplementedMarker = { readonly NotImplementedMarker: unique symbol };
|
||||
type ArrayMarker = { readonly ArrayMarker: unique symbol };
|
||||
type ObjectMarker = { readonly ObjectMarker: unique symbol };
|
||||
|
||||
export type InferType<T> = ExpandRecursively<MakeUndefinedOptional<InferTypeInner<T>>>;
|
||||
export type InferType<T> = Expand<MakeUndefinedOptional<InferTypeInner<T>>>;
|
||||
|
||||
// Infer TypeScript type from SimpleSchema type.
|
||||
type InferTypeInner<T> =
|
||||
@@ -36,8 +42,10 @@ type InferTypeInner<T> =
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
T extends typeof Function ? Function :
|
||||
T extends typeof Number ? number :
|
||||
T extends typeof SimpleSchema.Integer ? number :
|
||||
T extends typeof Object ? ObjectMarker :
|
||||
T extends typeof String ? string :
|
||||
T extends typeof Date ? Date :
|
||||
T extends RegExp ? string :
|
||||
T extends TypedSimpleSchema<infer U> ? InferSchema<U> :
|
||||
NotImplementedMarker;
|
||||
@@ -50,8 +58,11 @@ export type InferField<Def extends Definition, Key extends keyof Def> =
|
||||
? Array<InferField<Def, `${Key}.$`>>
|
||||
: ObjectMarker extends InferTypeInner<Typ>
|
||||
? { [L in keyof Def as L extends `${Key}.${infer SubKey}` ? SubKey extends `${string}.${string}` ? never : SubKey : never]: InferField<Def, L> }
|
||||
: Def[Key] extends { allowedValues: infer Allowed extends string[] }
|
||||
? InferOptional<Def, Key, InferEnum<Allowed>>
|
||||
: Def[Key] extends { allowedValues: infer Allowed extends string[] } ? InferOptional<Def, Key, InferEnum<Allowed>>
|
||||
: Def[Key] extends { type: 'fieldToCompute' } ? FieldToCalculate
|
||||
: Def[Key] extends { type: 'computedOnlyField' } ? CalculatedOnlyField
|
||||
: Def[Key] extends { type: 'inlineCalculationFieldToCompute' } ? InlineCalculationFieldToCompute
|
||||
: Def[Key] extends { type: 'computedOnlyInlineCalculationField' } ? ComputedOnlyInlineCalculationField
|
||||
: InferOptional<Def, Key, InferTypeInner<Typ>>
|
||||
: NotImplementedMarker
|
||||
: NotImplementedMarker
|
||||
@@ -71,34 +82,9 @@ export type InferSchema<Def extends Definition> = InferField<
|
||||
& { [Key in keyof Def as Key extends string ? `.${Key}` : never]: Def[Key] }, ''
|
||||
>;
|
||||
|
||||
const testSchema = new TypedSimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
age: {
|
||||
type: Number,
|
||||
},
|
||||
children: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
defaultValue: [],
|
||||
},
|
||||
'children.$': {
|
||||
type: String,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
allowedValues: ['cat', 'dog'] as const,
|
||||
optional: true,
|
||||
}
|
||||
});
|
||||
|
||||
// expands object types recursively
|
||||
type ExpandRecursively<T> = T extends object
|
||||
export type ExpandRecursively<T> = T extends object
|
||||
? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never
|
||||
: T;
|
||||
|
||||
type testType = InferType<typeof testSchema>;
|
||||
|
||||
type subType = ExpandRecursively<testType>
|
||||
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
|
||||
Reference in New Issue
Block a user