mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 07:29:30 +02:00
[Dev] Moved type helpers to separate directory; (#6123)
* [Dev] Moved type helpers to separate directory; renamed `EnumValues` to `ObjectValues` and enforced usage * Update tsconfig.json Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Fixed import issue * Updated documentation slightly --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Dean <69436131+emdeann@users.noreply.github.com>
This commit is contained in:
parent
17eeceb4f3
commit
1ae69a4183
@ -1,6 +1,6 @@
|
||||
import type { ArenaTagTypeMap } from "#data/arena-tag";
|
||||
import type { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import type { NonFunctionProperties } from "./type-helpers";
|
||||
import type { NonFunctionProperties } from "#types/type-helpers";
|
||||
|
||||
/** Subset of {@linkcode ArenaTagType}s that apply some negative effect to pokemon that switch in ({@link https://bulbapedia.bulbagarden.net/wiki/List_of_moves_that_cause_entry_hazards#List_of_traps | entry hazards} and Imprison. */
|
||||
export type ArenaTrapTagType =
|
||||
|
@ -1,18 +1,14 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/** Union type accepting any TS Enum or `const object`, with or without reverse mapping. */
|
||||
export type EnumOrObject = Record<string | number, string | number>;
|
||||
|
||||
/**
|
||||
* Utility type to extract the enum values from a `const object`,
|
||||
* or convert an `enum` interface produced by `typeof Enum` into the union type representing its values.
|
||||
*/
|
||||
export type EnumValues<E> = E[keyof E];
|
||||
|
||||
/**
|
||||
* Generic type constraint representing a TS numeric enum with reverse mappings.
|
||||
* @example
|
||||
* TSNumericEnum<typeof WeatherType>
|
||||
*/
|
||||
export type TSNumericEnum<T extends EnumOrObject> = number extends EnumValues<T> ? T : never;
|
||||
export type TSNumericEnum<T extends EnumOrObject> = number extends ObjectValues<T> ? T : never;
|
||||
|
||||
/** Generic type constraint representing a non reverse-mapped TS enum or `const object`. */
|
||||
export type NormalEnum<T extends EnumOrObject> = Exclude<T, TSNumericEnum<T>>;
|
@ -6,8 +6,6 @@
|
||||
import type { AbAttr } from "#abilities/ability";
|
||||
// biome-ignore-end lint/correctness/noUnusedImports: Used in a tsdoc comment
|
||||
|
||||
import type { EnumValues } from "#types/enum-types";
|
||||
|
||||
/**
|
||||
* Exactly matches the type of the argument, preventing adding additional properties.
|
||||
*
|
||||
@ -37,16 +35,25 @@ export type Mutable<T> = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Type helper to obtain the keys associated with a given value inside a `const object`.
|
||||
* Type helper to obtain the keys associated with a given value inside an object.
|
||||
* @typeParam O - The type of the object
|
||||
* @typeParam V - The type of one of O's values
|
||||
*/
|
||||
export type InferKeys<O extends Record<keyof any, unknown>, V extends EnumValues<O>> = {
|
||||
export type InferKeys<O extends object, V extends ObjectValues<O>> = {
|
||||
[K in keyof O]: O[K] extends V ? K : never;
|
||||
}[keyof O];
|
||||
|
||||
/**
|
||||
* Type helper that matches any `Function` type. Equivalent to `Function`, but will not raise a warning from Biome.
|
||||
* Utility type to obtain the values of a given object. \
|
||||
* Functions similar to `keyof E`, except producing the values instead of the keys.
|
||||
* @remarks
|
||||
* This can be used to convert an `enum` interface produced by `typeof Enum` into the union type representing its members.
|
||||
*/
|
||||
export type ObjectValues<E extends object> = E[keyof E];
|
||||
|
||||
/**
|
||||
* Type helper that matches any `Function` type.
|
||||
* Equivalent to `Function`, but will not raise a warning from Biome.
|
||||
*/
|
||||
export type AnyFn = (...args: any[]) => any;
|
||||
|
||||
@ -65,6 +72,7 @@ export type NonFunctionProperties<T> = {
|
||||
|
||||
/**
|
||||
* Type helper to extract out non-function properties from a type, recursively applying to nested properties.
|
||||
* This can be used to mimic the effects of JSON serialization and de-serialization on a given type.
|
||||
*/
|
||||
export type NonFunctionPropertiesRecursive<Class> = {
|
||||
[K in keyof Class as Class[K] extends AnyFn ? never : K]: Class[K] extends Array<infer U>
|
@ -3,6 +3,7 @@
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { ModifierConstructorMap } from "#modifiers/modifier";
|
||||
import type { ModifierType, WeightedModifierType } from "#modifiers/modifier-type";
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
export type ModifierTypeFunc = () => ModifierType;
|
||||
export type WeightedModifierTypeWeightFunc = (party: Pokemon[], rerollCount?: number) => number;
|
||||
@ -19,7 +20,7 @@ export type ModifierInstanceMap = {
|
||||
/**
|
||||
* Union type of all modifier constructors.
|
||||
*/
|
||||
export type ModifierClass = ModifierConstructorMap[keyof ModifierConstructorMap];
|
||||
export type ModifierClass = ObjectValues<ModifierConstructorMap>;
|
||||
|
||||
/**
|
||||
* Union type of all modifier names as strings.
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { PhaseConstructorMap } from "#app/phase-manager";
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
// Intentionally export the types of everything in phase-manager, as this file is meant to be
|
||||
// the centralized place for type definitions for the phase system.
|
||||
@ -17,7 +18,7 @@ export type PhaseMap = {
|
||||
/**
|
||||
* Union type of all phase constructors.
|
||||
*/
|
||||
export type PhaseClass = PhaseConstructorMap[keyof PhaseConstructorMap];
|
||||
export type PhaseClass = ObjectValues<PhaseConstructorMap>;
|
||||
|
||||
/**
|
||||
* Union type of all phase names as strings.
|
||||
|
@ -1,3 +1,5 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/**
|
||||
* Not to be confused with an Ability Attribute.
|
||||
* This is an object literal storing the slot that an ability can occupy.
|
||||
@ -8,4 +10,4 @@ export const AbilityAttr = Object.freeze({
|
||||
ABILITY_HIDDEN: 4,
|
||||
});
|
||||
|
||||
export type AbilityAttr = typeof AbilityAttr[keyof typeof AbilityAttr];
|
||||
export type AbilityAttr = ObjectValues<typeof AbilityAttr>;
|
@ -1,3 +1,5 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
export const DexAttr = Object.freeze({
|
||||
NON_SHINY: 1n,
|
||||
SHINY: 2n,
|
||||
@ -8,4 +10,4 @@ export const DexAttr = Object.freeze({
|
||||
VARIANT_3: 64n,
|
||||
DEFAULT_FORM: 128n,
|
||||
});
|
||||
export type DexAttr = typeof DexAttr[keyof typeof DexAttr];
|
||||
export type DexAttr = ObjectValues<typeof DexAttr>;
|
||||
|
@ -1,7 +1,9 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
export const GachaType = Object.freeze({
|
||||
MOVE: 0,
|
||||
LEGENDARY: 1,
|
||||
SHINY: 2
|
||||
});
|
||||
|
||||
export type GachaType = typeof GachaType[keyof typeof GachaType];
|
||||
export type GachaType = ObjectValues<typeof GachaType>;
|
||||
|
@ -1,3 +1,5 @@
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/** The result of a hit check calculation */
|
||||
export const HitCheckResult = {
|
||||
/** Hit checks haven't been evaluated yet in this pass */
|
||||
@ -20,4 +22,4 @@ export const HitCheckResult = {
|
||||
ERROR: 8,
|
||||
} as const;
|
||||
|
||||
export type HitCheckResult = typeof HitCheckResult[keyof typeof HitCheckResult];
|
||||
export type HitCheckResult = ObjectValues<typeof HitCheckResult>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { EnumOrObject, EnumValues, NormalEnum, TSNumericEnum } from "#app/@types/enum-types";
|
||||
import type { InferKeys } from "#app/@types/type-helpers";
|
||||
import type { EnumOrObject, NormalEnum, TSNumericEnum } from "#types/enum-types";
|
||||
import type { InferKeys, ObjectValues } from "#types/type-helpers";
|
||||
|
||||
/**
|
||||
* Return the string keys of an Enum object, excluding reverse-mapped numbers.
|
||||
@ -61,7 +61,7 @@ export function getEnumValues<E extends EnumOrObject>(enumType: TSNumericEnum<E>
|
||||
* If multiple keys map to the same value, the first one (in insertion order) will be retrieved,
|
||||
* but the return type will be the union of ALL their corresponding keys.
|
||||
*/
|
||||
export function enumValueToKey<T extends EnumOrObject, V extends EnumValues<T>>(
|
||||
export function enumValueToKey<T extends EnumOrObject, V extends ObjectValues<T>>(
|
||||
object: NormalEnum<T>,
|
||||
val: V,
|
||||
): InferKeys<T, V> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import type { EnumOrObject, EnumValues, NormalEnum, TSNumericEnum } from "#app/@types/enum-types";
|
||||
import type { enumValueToKey, getEnumKeys, getEnumValues } from "#app/utils/enums";
|
||||
import type { EnumOrObject, NormalEnum, TSNumericEnum } from "#types/enum-types";
|
||||
import type { ObjectValues } from "#types/type-helpers";
|
||||
import { describe, expectTypeOf, it } from "vitest";
|
||||
|
||||
enum testEnumNum {
|
||||
@ -16,21 +17,33 @@ const testObjNum = { testON1: 1, testON2: 2 } as const;
|
||||
|
||||
const testObjString = { testOS1: "apple", testOS2: "banana" } as const;
|
||||
|
||||
describe("Enum Type Helpers", () => {
|
||||
describe("EnumValues", () => {
|
||||
it("should go from enum object type to value type", () => {
|
||||
expectTypeOf<EnumValues<typeof testEnumNum>>().toEqualTypeOf<testEnumNum>();
|
||||
expectTypeOf<EnumValues<typeof testEnumNum>>().branded.toEqualTypeOf<1 | 2>();
|
||||
interface testObject {
|
||||
key_1: "1";
|
||||
key_2: "2";
|
||||
key_3: "3";
|
||||
}
|
||||
|
||||
expectTypeOf<EnumValues<typeof testEnumString>>().toEqualTypeOf<testEnumString>();
|
||||
expectTypeOf<EnumValues<typeof testEnumString>>().toEqualTypeOf<testEnumString.testS1 | testEnumString.testS2>();
|
||||
expectTypeOf<EnumValues<typeof testEnumString>>().toMatchTypeOf<"apple" | "banana">();
|
||||
describe("Enum Type Helpers", () => {
|
||||
describe("ObjectValues", () => {
|
||||
it("should produce a union of an object's values", () => {
|
||||
expectTypeOf<ObjectValues<testObject>>().toEqualTypeOf<"1" | "2" | "3">();
|
||||
});
|
||||
|
||||
it("should go from enum object type to value type", () => {
|
||||
expectTypeOf<ObjectValues<typeof testEnumNum>>().toEqualTypeOf<testEnumNum>();
|
||||
expectTypeOf<ObjectValues<typeof testEnumNum>>().branded.toEqualTypeOf<1 | 2>();
|
||||
|
||||
expectTypeOf<ObjectValues<typeof testEnumString>>().toEqualTypeOf<testEnumString>();
|
||||
expectTypeOf<ObjectValues<typeof testEnumString>>().toEqualTypeOf<
|
||||
testEnumString.testS1 | testEnumString.testS2
|
||||
>();
|
||||
|
||||
expectTypeOf<ObjectValues<typeof testEnumString>>().toExtend<"apple" | "banana">();
|
||||
});
|
||||
|
||||
it("should produce union of const object values as type", () => {
|
||||
expectTypeOf<EnumValues<typeof testObjNum>>().toEqualTypeOf<1 | 2>();
|
||||
|
||||
expectTypeOf<EnumValues<typeof testObjString>>().toEqualTypeOf<"apple" | "banana">();
|
||||
expectTypeOf<ObjectValues<typeof testObjNum>>().toEqualTypeOf<1 | 2>();
|
||||
expectTypeOf<ObjectValues<typeof testObjString>>().toEqualTypeOf<"apple" | "banana">();
|
||||
});
|
||||
});
|
||||
|
||||
@ -38,7 +51,6 @@ describe("Enum Type Helpers", () => {
|
||||
it("should match numeric enums", () => {
|
||||
expectTypeOf<TSNumericEnum<typeof testEnumNum>>().toEqualTypeOf<typeof testEnumNum>();
|
||||
});
|
||||
|
||||
it("should not match string enums or const objects", () => {
|
||||
expectTypeOf<TSNumericEnum<typeof testEnumString>>().toBeNever();
|
||||
expectTypeOf<TSNumericEnum<typeof testObjNum>>().toBeNever();
|
||||
@ -59,19 +71,19 @@ describe("Enum Type Helpers", () => {
|
||||
|
||||
describe("EnumOrObject", () => {
|
||||
it("should match any enum or const object", () => {
|
||||
expectTypeOf<typeof testEnumNum>().toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<typeof testEnumString>().toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<typeof testObjNum>().toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<typeof testObjString>().toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<typeof testEnumNum>().toExtend<EnumOrObject>();
|
||||
expectTypeOf<typeof testEnumString>().toExtend<EnumOrObject>();
|
||||
expectTypeOf<typeof testObjNum>().toExtend<EnumOrObject>();
|
||||
expectTypeOf<typeof testObjString>().toExtend<EnumOrObject>();
|
||||
});
|
||||
|
||||
it("should not match an enum value union w/o typeof", () => {
|
||||
expectTypeOf<testEnumNum>().not.toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<testEnumString>().not.toMatchTypeOf<EnumOrObject>();
|
||||
expectTypeOf<testEnumNum>().not.toExtend<EnumOrObject>();
|
||||
expectTypeOf<testEnumString>().not.toExtend<EnumOrObject>();
|
||||
});
|
||||
|
||||
it("should be equivalent to `TSNumericEnum | NormalEnum`", () => {
|
||||
expectTypeOf<EnumOrObject>().branded.toEqualTypeOf<TSNumericEnum<EnumOrObject> | NormalEnum<EnumOrObject>>();
|
||||
expectTypeOf<EnumOrObject>().toEqualTypeOf<TSNumericEnum<EnumOrObject> | NormalEnum<EnumOrObject>>();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -80,6 +92,7 @@ describe("Enum Functions", () => {
|
||||
describe("getEnumKeys", () => {
|
||||
it("should retrieve keys of numeric enum", () => {
|
||||
expectTypeOf<typeof getEnumKeys<typeof testEnumNum>>().returns.toEqualTypeOf<("testN1" | "testN2")[]>();
|
||||
expectTypeOf<typeof getEnumKeys<typeof testObjNum>>().returns.toEqualTypeOf<("testON1" | "testON2")[]>();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
"./system/*.ts"
|
||||
],
|
||||
"#trainers/*": ["./data/trainers/*.ts"],
|
||||
"#types/*": ["./@types/*.ts", "./typings/phaser/*.ts"],
|
||||
"#types/*": ["./@types/helpers/*.ts", "./@types/*.ts", "./typings/phaser/*.ts"],
|
||||
"#ui/*": ["./ui/battle-info/*.ts", "./ui/settings/*.ts", "./ui/*.ts"],
|
||||
"#utils/*": ["./utils/*.ts"],
|
||||
"#data/*": ["./data/pokemon-forms/*.ts", "./data/pokemon/*.ts", "./data/*.ts"],
|
||||
|
Loading…
Reference in New Issue
Block a user