Change decorator varargs to Generic variants

This commit is contained in:
Seth Posner 2023-04-19 17:49:15 -07:00
parent 7065de519f
commit 27d678a30b
11 changed files with 27 additions and 22 deletions

View file

@ -2,7 +2,7 @@ import { computed } from "@vue/reactivity";
import { isArray } from "@vue/shared";
import Select from "components/fields/Select.vue";
import AchievementComponent from "features/achievements/Achievement.vue";
import { Decorator } from "features/decorators/common";
import { Decorator, GenericDecorator } from "features/decorators/common";
import {
CoercableComponent,
Component,
@ -139,7 +139,7 @@ export type GenericAchievement = Replace<
*/
export function createAchievement<T extends AchievementOptions>(
optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>,
...decorators: Decorator<T, BaseAchievement, GenericAchievement>[]
...decorators: GenericDecorator[]
): Achievement<T> {
const earned = persistent<boolean>(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});

View file

@ -31,7 +31,7 @@ import { coerceComponent, isCoercableComponent, render } from "util/vue";
import { computed, Ref, ref, unref } from "vue";
import { BarOptions, createBar, GenericBar } from "./bars/bar";
import { ClickableOptions } from "./clickables/clickable";
import { Decorator } from "./decorators/common";
import { Decorator, GenericDecorator } from "./decorators/common";
/** A symbol used to identify {@link Action} features. */
export const ActionType = Symbol("Action");
@ -104,7 +104,7 @@ export type GenericAction = Replace<
*/
export function createAction<T extends ActionOptions>(
optionsFunc?: OptionsFunc<T, BaseAction, GenericAction>,
...decorators: Decorator<T, BaseAction, GenericAction>[]
...decorators: GenericDecorator[]
): Action<T> {
const progress = persistent<DecimalSource>(0);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});

View file

@ -1,5 +1,5 @@
import BarComponent from "features/bars/Bar.vue";
import { Decorator } from "features/decorators/common";
import { Decorator, GenericDecorator } from "features/decorators/common";
import type {
CoercableComponent,
GenericComponent,
@ -103,7 +103,7 @@ export type GenericBar = Replace<
*/
export function createBar<T extends BarOptions>(
optionsFunc: OptionsFunc<T, BaseBar, GenericBar>,
...decorators: Decorator<T, BaseBar, GenericBar>[]
...decorators: GenericDecorator[]
): Bar<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(feature => {

View file

@ -1,7 +1,7 @@
import { isArray } from "@vue/shared";
import Toggle from "components/fields/Toggle.vue";
import ChallengeComponent from "features/challenges/Challenge.vue";
import { Decorator } from "features/decorators/common";
import { Decorator, GenericDecorator } from "features/decorators/common";
import type {
CoercableComponent,
GenericComponent,
@ -150,7 +150,7 @@ export type GenericChallenge = Replace<
*/
export function createChallenge<T extends ChallengeOptions>(
optionsFunc: OptionsFunc<T, BaseChallenge, GenericChallenge>,
...decorators: Decorator<T, BaseChallenge, GenericChallenge>[]
...decorators: GenericDecorator[]
): Challenge<T> {
const completions = persistent(0);
const active = persistent(false, false);

View file

@ -1,5 +1,5 @@
import ClickableComponent from "features/clickables/Clickable.vue";
import { Decorator } from "features/decorators/common";
import { Decorator, GenericDecorator } from "features/decorators/common";
import type {
CoercableComponent,
GenericComponent,
@ -97,7 +97,7 @@ export type GenericClickable = Replace<
*/
export function createClickable<T extends ClickableOptions>(
optionsFunc?: OptionsFunc<T, BaseClickable, GenericClickable>,
...decorators: Decorator<T, BaseClickable, GenericClickable>[]
...decorators: GenericDecorator[]
): Clickable<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(feature => {

View file

@ -15,7 +15,7 @@ import { convertComputable, processComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
import type { Ref } from "vue";
import { computed, unref } from "vue";
import { Decorator } from "./decorators/common";
import { GenericDecorator } from "./decorators/common";
/** An object that configures a {@link Conversion}. */
export interface ConversionOptions {
@ -125,7 +125,7 @@ export type GenericConversion = Replace<
*/
export function createConversion<T extends ConversionOptions>(
optionsFunc: OptionsFunc<T, BaseConversion, GenericConversion>,
...decorators: Decorator<T, BaseConversion, GenericConversion>[]
...decorators: GenericDecorator[]
): Conversion<T> {
return createLazyProxy(feature => {
const conversion = optionsFunc.call(feature, feature);

View file

@ -15,11 +15,13 @@ export interface BonusCompletionsFeatureOptions {
export interface BaseBonusAmountFeature {
amount: Ref<DecimalSource>;
totalAmount: Ref<DecimalSource>;
bonusAmount: ProcessedComputable<DecimalSource>;
totalAmount?: Ref<DecimalSource>;
}
export interface BaseBonusCompletionsFeature {
completions: Ref<DecimalSource>;
totalCompletions: Ref<DecimalSource>;
bonusCompletions: ProcessedComputable<DecimalSource>;
totalCompletions?: Ref<DecimalSource>;
}
export type BonusAmountFeature<T extends BonusAmountFeatureOptions> = Replace<
@ -47,6 +49,7 @@ export type GenericBonusCompletionsFeature = Replace<
/**
* Allows the addition of "bonus levels" to the decorated feature, with an accompanying "total amount".
* To function properly, the `createFeature()` function must have its generic type extended by {@linkcode BonusAmountFeatureOptions}.
* Additionally, the base feature must have an `amount` property.
* To allow access to the decorated values outside the `createFeature()` function, the output type must be extended by {@linkcode GenericBonusAmountFeature}.
* @example ```ts
* createRepeatable<RepeatableOptions & BonusAmountFeatureOptions>(() => ({

View file

@ -2,13 +2,15 @@ import { Replace, OptionsObject } from "../feature";
import { Computable, GetComputableType, processComputable, ProcessedComputable } from "util/computed";
import { Persistent, State } from "game/persistence";
export type Decorator<FeatureOptions, BaseFeature = {}, GenericFeature = BaseFeature, S extends State = State> = {
export type Decorator<FeatureOptions, BaseFeature = Object, GenericFeature = BaseFeature, S extends State = State> = {
getPersistentData?(): Record<string, Persistent<S>>;
preConstruct?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): void;
postConstruct?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): void;
getGatheredProps?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): Partial<OptionsObject<FeatureOptions,BaseFeature,GenericFeature>>
}
export type GenericDecorator = Decorator<unknown>;
export interface EffectFeatureOptions {
effect: Computable<any>;
}
@ -33,7 +35,7 @@ export type GenericEffectFeature = Replace<
* }), effectDecorator) as GenericUpgrade & GenericEffectFeature;
* ```
*/
export const effectDecorator: Decorator<EffectFeatureOptions, {}, GenericEffectFeature> = {
export const effectDecorator: Decorator<EffectFeatureOptions, unknown, GenericEffectFeature> = {
postConstruct(feature) {
processComputable(feature, "effect");
}

View file

@ -30,7 +30,7 @@ import { createLazyProxy } from "util/proxies";
import { coerceComponent, isCoercableComponent } from "util/vue";
import type { Ref } from "vue";
import { computed, unref } from "vue";
import { Decorator } from "./decorators/common";
import { Decorator, GenericDecorator } from "./decorators/common";
/** A symbol used to identify {@link Repeatable} features. */
export const RepeatableType = Symbol("Repeatable");
@ -131,11 +131,11 @@ export type GenericRepeatable = Replace<
*/
export function createRepeatable<T extends RepeatableOptions>(
optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable>,
...decorators: Decorator<T, BaseRepeatable, GenericRepeatable>[]
...decorators: GenericDecorator[]
): Repeatable<T> {
const amount = persistent<DecimalSource>(0);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(feature => {
return createLazyProxy<Repeatable<T>, Repeatable<T>>(feature => {
const repeatable = optionsFunc.call(feature, feature);
repeatable.id = getUniqueID("repeatable-");

View file

@ -1,4 +1,4 @@
import { Decorator } from "features/decorators/common";
import { Decorator, GenericDecorator } from "features/decorators/common";
import type {
CoercableComponent,
GenericComponent,
@ -103,7 +103,7 @@ export type GenericTreeNode = Replace<
*/
export function createTreeNode<T extends TreeNodeOptions>(
optionsFunc?: OptionsFunc<T, BaseTreeNode, GenericTreeNode>,
...decorators: Decorator<T, BaseTreeNode, GenericTreeNode>[]
...decorators: GenericDecorator[]
): TreeNode<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(feature => {

View file

@ -119,7 +119,7 @@ export type GenericUpgrade = Replace<
*/
export function createUpgrade<T extends UpgradeOptions>(
optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>,
...decorators: Decorator<T, BaseUpgrade, GenericUpgrade>[]
...decorators: GenericDecorator[]
): Upgrade<T> {
const bought = persistent<boolean>(false, false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});