- Installation
- Similar projects (by others)
- Motivation
- Future features
- 1. How to use it (the base)
- 2. Utilizing the default value
- 3. Excluding some values
- 4. Inheritance by a single parent
- Inheritance by a composed parent
- 5. Inheritance by more than one parent (2 or 3)
- 6. Inheritance by more than three parents
- 7. Companion enum
- Common mistakes
- Known error
- Contribution
npm install @joookiwi/enumerable
npm i @joookiwi/enumerable
npm install --save @joookiwi/enumerable
npm i -S @joookiwi/enumerable
npm install --save-dev @joookiwi/enumerable
npm i -D @joookiwi/enumerable
Here are some related projects. They don't contain any unfinished version (like 0.0.1 or 0.1.0). Some features may be different. They could also have a different approach, but eventually, some features could be added to give simplicity.
- Discope enumeration by dpimonov (1.0 on December 2022)
- Enum by voidVolker (1.0 on October 2023)
- Enum expansion by iShawnWang (1.0 on April 2022)
- Enum support by northScaler (4.3 on September 2023)
- Enumify by rauschma (2.0 on January 2020)
- Js enum by stein197 (2.1 on July 2022)
- Simple enum by byteJoey (1.1 on May 2017)
- Simple js enum by yevhendiachenko (1.0 on January 2018)
The Typescript enums
are overly simple.
They don't have a great support for other values that are not a string
or a number
).
And that is not even including a behaviour enum or a classed-based enum.
The usage of almost no static values is with the mindset of Kotlin
.
The goal is to have an implementation of an enum class
usable for either Javascript
or Typescript
.
Some features are still missing from this project.
Notably the way to verify if a value exists within the enum class
.
No release date or order is made to the features,
but they should be added eventually.
hasValue(value: PossibleEnumerableValue)
hasName(value: PossibleEnumerableValue)
-
hasOrdinal(value: PossibleEnumerableValue)
newEnum(values: Iterable<string>)
newEnum(values: Iterable<string>, parent: Enumerable)
newEnum(values: Iterable<string>, parent: EnumerableWithParent, grandParent: Enumerable)
-
newEnum(values: Iterable<string>, parent: EnumerableWithGrandParent, grandParent: EnumerableWithParent, greatGrandParent: Enumerable)
newCompanionEnum(instance: Enumerable)
newCompanionEnum(instance: EnumerableWithParent, parentInstance: Enumerable)
newCompanionEnum(instance: EnumerableWithGrandParent, parentInstance: EnumerableWithParent, grandParentInstance: Enumerable)
-
newCompanionEnum(instance: EnumerableWithGreatGrandParent, parentInstance: EnumerableWithGrandParent, grandParentInstance: EnumerableWithParent, greatGrandParentInstance: Enumerable)
EnumWithDoubleParent
EnumWithTripleParent
EnumWithDoubleGrandParent
EnumWithTripleGrandParent
EnumWithDoubleGreatGrandParent
EnumWithTripleGreatGrandParent
CompanionEnumWithDoubleParent
CompanionEnumWithTripleParent
CompanionEnumWithDoubleGrandParent
CompanionEnumWithTripleGrandParent
CompanionEnumWithDoubleGreatGrandParent
CompanionEnumWithTripleGreatGrandParent
To properly use the enum class
, there is really one required field.
public static readonly CompanionEnum
.
The rest is only there to give flexibility toward the initialization
(in Javascript
and in Typescript
).
The flexibility is separated in three parts.
The excluded values in the companion enum
protected readonly _EXCLUDED_NAMES
.
The default value for the getValue
, getName
and getOrdinal
methods.
This has an order of precedence depending on the return value (if it is null).
It starts by
protected readonly _DEFAULT
or protected readonly _DEFAULT_NAME
or protected readonly _DEFAULT_ORDINAL
or NullEnumerableException
thrown.
The third part (optional) is in Typescript
to add the ordinal to the enum class
type definition.
static O: EnumType.N
with O
and N
as their specific ordinal and name respectively
Javascript
import {CompanionEnum, Enum} from "@joookiwi/enumerable"
export class Example extends Enum {
static A = new Example()
static B = new Example()
static C = new Example()
static CompanionEnum = class CompanionEnum_Example extends CompanionEnum {
static #instance
constructor() { super(Example,) }
static get get() { return CompanionEnum_Example.#instance ??= new CompanionEnum_Example() }
}
// The class content starts here
}
Typescript
// Example.ts
import {CompanionEnum, Enum} from "@joookiwi/enumerable"
import type {CompanionEnumSingleton} from "@joookiwi/enumerable/dist/types"
import type {Names, Ordinals} from "./Example.types"
export class Example extends Enum<Ordinals, Names> {
public static readonly A = new Example()
public static readonly B = new Example()
public static readonly C = new Example()
// Optional ordinal typing (start)
public static readonly 0: typeof Example.A
public static readonly 1: typeof Example.B
public static readonly 2: typeof Example.C
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumSingleton<Example, typeof Example> =
class CompanionEnum_Example extends CompanionEnum<Example, typeof Example> {
static #instance?: CompanionEnum_Example
private constructor() { super(Example,) }
public static get get() { return CompanionEnum_Example.#instance ??= new CompanionEnum_Example() }
}
private constructor() { super() }
// The class content starts here
}
// Example.types.ts
type Enum = {
A: 0
B: 1
C: 2
}
export type Names = keyof Enum
export type Ordinals = Enum[Names]
To have a default value, it can be triggered in two different ways. The first is via its initialization and the second, via its setter methods.
It may be possible to change the default value after its initialization by calling the CompanionEnum.defaultValue
setter.
Example.CompanionEnum.defaultValue = 'A' // By name
Example.CompanionEnum.defaultValue = 1 // By ordinal
Example.CompanionEnum.defaultValue = Example.C // By enumerable (current)
Example.CompanionEnum.defaultValue = ParentExample.C // By enumerable (parent)
The other way to have a default value (for the getValue
, getName
or getOrdinal
) is during its initialization
The method CompanionEnum.defaultValue
will only be called if no value has been set.
Note that null or undefined are a valid value to unset,
but nothing can uninitialized the value once it has been set.
It looks in order _DEFAULT
(for a valid Enumerable
),
_DEFAULT_NAME
(for a string)
and _DEFAULT_ORDINAL
(for a number or
a bigint).
And sending a primitive or an object doesn't matter at the end of the process.
Javascript
class CompanionEnum_Example extends CompanionEnum {
_DEFAULT = condition1 ? Example.B : null
_DEFAULT_NAME = condition2 ? 'C' : null
get _DEFAULT_ORDINAL() {
// Some code to get something for an ordinal
return defaultValueByOrdinal
}
}
Typescript
class CompanionEnum_Example extends CompanionEnum<Example, typeof Example> {
protected override readonly _DEFAULT = condition1 ? Example.B : null
protected override readonly _DEFAULT_NAME = condition2 ? 'C' as const satisfies Names : null
protected override get _DEFAULT_ORDINAL() {
// Some code to get something for an ordinal
return defaultValueByOrdinal satisfies PossibleNumeric<Ordinals>
}
}
It can happen to have interpreted values in the instance.
Or it is also possible to have values that should not be counted as a enum
instance.
In cases like these, override the excluded names in the companion enum.
Note that a method (getter, setter or function) will never be counted as a possible instance of enum
.
Javascript
class Example extends Enum {
static A = new Example()
static B = new Example()
static C = new Example()
static D = someReason ? Example.A : Example.B
static SOME_FIELD = Example.D
static get ALREADY_EXSLUDED_GETTER() { return Example.A }
static CompanionEnum = class CompanionEnum_Example extends CompanionEnum {
_EXCLUDED_NAMES = ['D', "SOME_FIELD",]
}
}
Typescript
class Example extends Enum<Ordinals, Names> {
public static readonly A = new Example()
public static readonly B = new Example()
public static readonly C = new Example()
public static readonly D = someReason ? Example.A : Example.B
public static readonly SOME_FIELD = Example.D
public static get ALREADY_EXSLUDED_GETTER() { return Example.A }
public static readonly CompanionEnum: CompanionEnumSingleton<Example, typeof Example> =
class CompanionEnum_Example extends CompanionEnum<Example, typeof Example> {
protected readonly _EXCLUDED_NAMES = ['D', "SOME_FIELD",]
}
}
In practice, it is possible to have a desire to inherit another enum
,
but in practice, enum class
are final
and cannot be extended.
But it can be done indirectly via EnumWithParent
, EnumWithNullableParent
,
EnumerableWithNullableParent
and EnumerableWithParent
in juncture with CompanionEnumWithParent
or CompanionEnumWithParentDeclaration
.
There are some possibilities on how it can be implemented, but the result is always the same.
Note that there are some things
to handle correctly when using the EnumWithParent
or EnumWithNullableParent
instances:
- The symbols
ENUM_REFERENCE_BY_ITS_NAME_SYMBOL
is there as an alternative to no arguments - The symbols
NULL_ENUM_REFERENCE_SYMBOL
is there as an alternative tonull
/undefined
- Giving no arguments or
null
/undefined
is different - Giving a name (
string
) is permitted - Giving an ordinal (
number
orbigint
) is prohibited (the order cannot be assured from the child compared to the parent)
Javascript
// ParentEnum.js
import {CompanionEnum, Enum} from "@joookiwi/enumerable"
export class ParentEnum extends Enum {
static A = new ParentEnum()
static B = new ParentEnum()
static CompanionEnum = class CompanionEnum_ParentEnum extends CompanionEnum {
static #instance
constructor() { super(ParentEnum,) }
static get get() { return CompanionEnum.#instance ??= new CompanionEnum() }
}
}
EnumWithParent (from a value)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumWithNullableParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithNullableParent {
/** @readonly */ static A = new ChildEnum(ParentEnum.A,)
/** @readonly */ static B = new ChildEnum(ParentEnum.B,)
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor(parent = null) { super(parent,) }
}
EnumWithParent (inferred, but slowest)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumWithParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithParent {
/** @readonly */ static A = new ChildEnum()
/** @readonly */ static B = new ChildEnum()
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor() { super() }
}
EnumWithParent (by name, but slower)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumWithParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithParent {
/** @readonly */ static A = new ChildEnum('A',)
/** @readonly */ static B = new ChildEnum('B',)
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor(parent) { super(parent,) }
}
EnumWithNullableParent (value upfront)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumWithNullableParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithNullableParent {
/** @readonly */ static A = new ChildEnum(ParentEnum.A,)
/** @readonly */ static B = new ChildEnum(ParentEnum.B,)
/** @readonly */ static C = new ChildEnum()
/** @readonly */ static D = new ChildEnum()
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor(parent = null) { super(parent,) }
}
EnumWithNullableParent (name upfront, but slower)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumWithNullableParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithNullableParent {
/** @readonly */ static A = new ChildEnum('A',)
/** @readonly */ static B = new ChildEnum('B',)
/** @readonly */ static C = new ChildEnum()
/** @readonly */ static D = new ChildEnum()
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor(parent = null) { super(parent,) }
}
EnumWithNullableParent (null upfront, but slowest)
// ChildEnum.ts
import {CompanionEnumWithParent, EnumConstants, EnumWithNullableParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum extends EnumWithNullableParent {
/** @readonly */ static A = new ChildEnum()
/** @readonly */ static B = new ChildEnum()
/** @readonly */ static C = new ChildEnum(null,)
/** @readonly */ static D = new ChildEnum(null,)
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */ constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
/** @private */constructor(parent = EnumConstants.ENUM_REFERENCE_BY_ITS_NAME_SYMBOL) { super(parent,) }
}
EnumerableWithParent (manually declared)
// ChildEnum.ts
import {CompanionEnumWithParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
/** @implements {EnumerableWithParent} */
export class ChildEnum extends Enum {
/** @readonly */ static A = new ChildEnum(ParentEnum.A,)
/** @readonly */ static B = new ChildEnum(ParentEnum.B,)
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
#parent
/** @private */constructor(parent) { super(); this.#parent = parent }
get parent() { return this.#parent }
}
EnumerableWithNullableParent (manually declared)
// ChildEnum.ts
import {CompanionEnumWithParent} from "@joookiwi/enumerable"
import {ParentEnum} from "./ParentEnum"
/** @implements {EnumerableWithNullableParent} */
export class ChildEnum extends Enum {
/** @readonly */ static A = new ChildEnum(ParentEnum.A,)
/** @readonly */ static B = new ChildEnum(ParentEnum.B,)
/** @readonly */ static C = new ChildEnum()
/** @readonly */ static D = new ChildEnum()
static CompanionEnum = class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
/** @private */constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
#parent
/** @private */constructor(parent = null) { super(); this.#parent = parent }
get parent() { return this.#parent }
}
Typescript
// ParentEnum.ts
import {CompanionEnum, Enum} from "@joookiwi/enumerable"
import type {ParentOrdinals, ParentNames} from "./ParentEnum.types"
export class ParentEnum extends Enum<ParentOrdinals, ParentNames> {
public static readonly A = new ParentEnum()
public static readonly B = new ParentEnum()
// Optional ordinal typing (start)
public static readonly 0: typeof ParentEnum.A
public static readonly 1: typeof ParentEnum.B
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumSingleton<ParentEnum, typeof ParentEnum> =
class CompanionEnum_ParentEnum extends CompanionEnum<ParentEnum, typeof ParentEnum> {
static #instance?: CompanionEnum_ParentEnum
private constructor() { super(ParentEnum,) }
public static get get() { return CompanionEnum.#instance ??= new CompanionEnum() }
}
private constructor() { super() }
}
// ParentEnum.types.ts
type ParentEnumType = {
A: 0
B: 1
}
export type ParentNames = keyof ParentEnumType
export type ParentOrdinals = ParentEnumType[ParentNames]
// ChildEnum.types.ts
type ChildEnumType = {
A: 0
B: 1
C: 2
D: 3
}
export type ChildNames = keyof ChildEnumType
export type ChildOrdinals = ChildEnumType[ChildNames]
EnumWithParent (from a value)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithNullableParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithNullableParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum(ParentEnum.A,)
public static readonly B = new ChildEnum(ParentEnum.B,)
public static readonly C = new ChildEnum()
public static readonly D = new ChildEnum()
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor(parent: NullOr<ParentEnum> = null, ) { super(parent,) }
}
EnumWithParent (inferred, but slowest)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum()
public static readonly B = new ChildEnum()
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor() { super() }
}
EnumWithParent (by name, but slower)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum('A',)
public static readonly B = new ChildEnum('B',)
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor(parent: ParentNames,) { super(parent,) }
}
EnumWithNullableParent (value upfront)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum(ParentEnum.A,)
public static readonly B = new ChildEnum(ParentEnum.B,)
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor(parent: ParentEnum, ) { super(parent,) }
}
EnumWithNullableParent (name upfront, but slower)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithNullableParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithNullableParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum('A',)
public static readonly B = new ChildEnum('B',)
public static readonly C = new ChildEnum()
public static readonly D = new ChildEnum()
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
public static readonly 2: typeof ChildEnum.C
public static readonly 3: typeof ChildEnum.D
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor(parent: NullOr<ParentNames> = null,) { super(parent,) }
}
EnumWithNullableParent (null upfront, but slowest)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, NullOr, PossibleEnumSymbol} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, EnumConstants, EnumWithNullableParent} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
export class ChildEnum
extends EnumWithNullableParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum()
public static readonly B = new ChildEnum()
public static readonly C = new ChildEnum(null,)
public static readonly D = new ChildEnum(null,)
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
public static readonly 2: typeof ChildEnum.C
public static readonly 3: typeof ChildEnum.D
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
private constructor(parent: NullOr<PossibleEnumSymbol> = EnumConstants.ENUM_REFERENCE_BY_ITS_NAME_SYMBOL,) { super(parent,) }
}
EnumerableWithParent (manually declared)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, EnumerableWithParent, NullOr} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, Enum} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
class ChildEnum extends Enum<ChildOrdinals, ChildNames>
implements EnumerableWithParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum(ParentEnum.A,)
public static readonly B = new ChildEnum(ParentEnum.B,)
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance?: CompanionEnum_ChildEnum
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
readonly #parent
private constructor(parent: ParentEnum,) { super(); this.#parent = parent }
public get parent(): ParentEnum { return this.#parent }
}
EnumerableWithNullableParent (manually declared)
// ChildEnum.ts
import type {CompanionEnumWithParentSingleton, EnumerableWithNullableParent, NullOr} from "@joookiwi/enumerable"
import {CompanionEnumWithParent, Enum} from "@joookiwi/enumerable"
import type {ChildOrdinals, ChildNames} from "./ChildEnum.types"
import {ParentEnum} from "./ParentEnum"
class ChildEnum extends Enum<ChildOrdinals, ChildNames>
implements EnumerableWithNullableParent<ChildOrdinals, ChildNames, ParentEnum> {
public static readonly A = new ChildEnum(ParentEnum.A,)
public static readonly B = new ChildEnum(ParentEnum.B,)
public static readonly C = new ChildEnum()
public static readonly D = new ChildEnum()
// Optional ordinal typing (start)
public static readonly 0: typeof ChildEnum.A
public static readonly 1: typeof ChildEnum.B
public static readonly 2: typeof ChildEnum.C
public static readonly 3: typeof ChildEnum.D
// Optional ordinal typing (end)
public static readonly CompanionEnum: CompanionEnumWithParentSingleton<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> =
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance?: CompanionEnum_ChildEnum
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
readonly #parent
private constructor(parent: NullOr<ParentEnum> = null,) { super(); this.#parent = parent }
public get parent(): NullOr<ParentEnum> { return this.#parent }
}
This part hasn't been done in the project yet, but it will be added eventually.
The inheritance can continue from up to three instances in the chain.
The logic is always the same toward the nullable and non-nullable instances.
There is also a logic where an instance with nullable value can inherit both instances (nullable and non-null). But the opposite is not true.
non-null parent + non-null grand-parent (valid)
class Enum1 extends Enum { /*class content*/ }
class Enum2 extends EnumWithParent<Enum1> { /*class content*/ }
class Enum3 extends EnumWithGrandParent<Enum1, Enum2> { /*class content*/ }
nullable parent + non-null grand-parent (invalid)
class Enum1 extends Enum { /*class content*/ }
class Enum2 extends EnumWithNullableParent<Enum1> { /*class content*/ } // Is valid
class Enum3 extends EnumWithGrandParent<Enum1, Enum2> { /*class content*/ } // Is not possible
non-null parent + nullable grand-parent (valid)
class Enum1 extends Enum { /*class content*/ }
class Enum2 extends EnumWithParent<Enum1> { /*class content*/ }
class Enum3 extends EnumWithNullableGrandParent<Enum1, Enum2> { /*class content*/ }
nullable parent + nullable grand-parent (valid)
class Enum1 extends Enum { /*class content*/ }
class Enum2 extends EnumWithNullableParent<Enum1> { /*class content*/ }
class Enum3 extends EnumWithNullableGrandParent<Enum1, Enum2> { /*class content*/ }
The same logic is applicable for the great-grandparent instances.
If the inheritance is needed, it is still possible to extend
the currently defined predefined EnumWith***
or EnumerableWith***
.
The companion enum
instances are deeply linked to the enum class
instances.
But they don't really need to be directly used.
(All the empty bracket {}
are a custom implementation)
Javascript
CompanionEnum (simplest)
import {CompanionEnum} from "@joookiwi/enumerable"
class CustomCompanionEnum extends CompanionEnum {
/** @protected */ constructor() { super(Enum1,) }
}
CompanionEnumDeclaration (hardest, but fully customizable)
/** @implements CompanionEnumDeclaration */
class CustomCompanionEnum {
/** @readonly */ #instance
/** @protected */constructor() { this.#instance = Enum1 }
get instance() { return this.#instance }
get defaultValue() {}
set defaultValue(value) {}
setDefaultValue(value) { this.defaultValue = value; return this }
get values() {}
get names() {}
get ordinals() {}
get iterator() { return this.values[Symbol.iterator]() }
getValue(value) {}
getName(value) {}
getOrdinal(value) {}
[Symbol.iterator]() { return this.values[Symbol.iterator]() }
get [Symbol.toStringTag] () { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithParent (simplest)
import {CompanionEnumWithParent} from "@joookiwi/enumerable"
class CustomCompanionEnum extends CompanionEnumWithParent {
/** @protected */ constructor() { super(Enum1, Enum2,) }
}
CompanionEnumWithParentDeclaration (hardest, but fully customizable)
/** @implements CompanionEnumWithParentDeclaration */
class CustomCompanionEnum {
/** @readonly */ #instance
/** @readonly */ #parentInstance
/** @protected */constructor() {
this.#instance = Enum1
this.#parentInstance = Enum2
}
get instance() { return this.#instance }
get parentInstance() { return this.#parentInstance }
get defaultValue() {}
set defaultValue(value) {}
setDefaultValue(value) { this.defaultValue = value; return this }
get values() {}
get names() {}
get ordinals() {}
get iterator() { return this.values[Symbol.iterator]() }
getValue(value) {}
getName(value) {}
getOrdinal(value) {}
[Symbol.iterator]() { return this.values[Symbol.iterator]() }
get [Symbol.toStringTag] () { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithGrandParent (simplest)
import {CompanionEnumWithGrandParent} from "@joookiwi/enumerable"
class CustomCompanionEnum extends CompanionEnumWithGrandParent {
/** @protected */ constructor() { super(Enum1, Enum2, Enum3,) }
}
CompanionEnumWithGrandParentDeclaration (hardest, but fully customizable)
/** @implements CompanionEnumWithGrandParentDeclaration */
class CustomCompanionEnum {
/** @readonly */ #instance
/** @readonly */ #parentInstance
/** @readonly */ #grandParentInstance
/** @protected */constructor() {
this.#instance = Enum1
this.#parentInstance = Enum2
this.#grandParentInstance = Enum3
}
get instance() { return this.#instance }
get parentInstance() { return this.#parentInstance }
get grandParentInstance() { return this.#grandParentInstance }
get defaultValue() {}
set defaultValue(value) {}
setDefaultValue(value) { this.defaultValue = value; return this }
get values() {}
get names() {}
get ordinals() {}
get iterator() { return this.values[Symbol.iterator]() }
getValue(value) {}
getName(value) {}
getOrdinal(value) {}
[Symbol.iterator]() { return this.values[Symbol.iterator]() }
get [Symbol.toStringTag] () { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithGreatGrandParent (simplest)
import {CompanionEnumWithGreatGrandParent} from "@joookiwi/enumerable"
class CustomCompanionEnum extends CompanionEnumWithGreatGrandParent {
/** @protected */ constructor() { super(Enum1, Enum2, Enum3, Enum4,) }
}
CompanionEnumWithGreatGrandParentDeclaration (hardest, but fully customizable)
/** @implements CompanionEnumWithGreatGrandParentDeclaration */
class CustomCompanionEnum {
/** @readonly */ #instance
/** @readonly */ #parentInstance
/** @readonly */ #grandParentInstance
/** @readonly */ #greatGrandParentInstance
/** @protected */constructor() {
this.#instance = Enum1
this.#parentInstance = Enum2
this.#grandParentInstance = Enum3
this.#greatGrandParentInstance = Enum4
}
get instance() { return this.#instance }
get parentInstance() { return this.#parentInstance }
get grandParentInstance() { return this.#grandParentInstance }
get greatGrandParentInstance() { return this.#greatGrandParentInstance }
get defaultValue() {}
set defaultValue(value) {}
setDefaultValue(value) { this.defaultValue = value; return this }
get values() {}
get names() {}
get ordinals() {}
get iterator() { return this.values[Symbol.iterator]() }
getValue(value) {}
getName(value) {}
getOrdinal(value) {}
[Symbol.iterator]() { return this.values[Symbol.iterator]() }
get [Symbol.toStringTag] () { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
Typescript
CompanionEnum (simplest)
import {CompanionEnum} from "@joookiwi/enumerable"
class CustomCompanionEnum
extends CompanionEnum<Enum1, typeof Enum1> {
protected constructor() { super(Enum1,) }
}
CompanionEnumDeclaration (hardest, but fully customizable)
import type {CollectionHolder, CollectionIterator} from "@joookiwi/collection"
import type {CompanionEnumDeclaration, CompanionEnumName,
NameOf, Nullable, OrdinalOf, PossibleEnumerableValue} from "@joookiwi/enumerable"
class CustomCompanionEnum
implements CompanionEnumDeclaration<Enum1, typeof Enum1> {
readonly #instance
protected constructor() { this.#instance = Enum1 }
public get instance(): typeof Enum1 { return this.#instance }
public get defaultValue(): Enum1 {}
public set defaultValue(value: Nullable<PossibleEnumerableValue<Enum1>>,) {}
public setDefaultValue(value: Nullable<PossibleEnumerableValue<Enum1>>,): this { this.defaultValue = value; return this }
public get values(): CollectionHolder<Enum1> {}
public get names(): CollectionHolder<NameOf<Enum1>> {}
public get ordinals(): CollectionHolder<OrdinalOf<Enum1>> {}
public get iterator(): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public getValue(value: Nullable<PossibleEnumerableValue<Enum1>>,): Enum1 {}
public getName(value: Nullable<PossibleEnumerableValue<Enum1>>,): NameOf<Enum1> {}
public getOrdinal(value: Nullable<PossibleEnumerableValue<Enum1>>,): OrdinalOf<Enum1> {}
public [Symbol.iterator](): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public get [Symbol.toStringTag](): CompanionEnumName { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithParent (simplest)
import {CompanionEnumWithParent} from "@joookiwi/enumerable"
class CustomCompanionEnum
extends CompanionEnumWithParent<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2> { // parent
protected constructor() {
super(Enum1, Enum2,)
}
}
CompanionEnumWithParentDeclaration (hardest, but fully customizable)
import type {CollectionHolder, CollectionIterator} from "@joookiwi/collection"
import type {CompanionEnumWithParentDeclaration, CompanionEnumName,
NameOf, Nullable, OrdinalOf, PossibleEnumerableValue} from "@joookiwi/enumerable"
class CustomCompanionEnum
implements CompanionEnumWithParentDeclaration<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2> { // parent
readonly #instance
readonly #parentInstance
protected constructor() {
this.#instance = Enum1
this.#parentInstance = Emum2
}
public get instance(): typeof Enum1 { return this.#instance }
public get parentInstance(): typeof Enum2{ return this.#parentInstance }
public get defaultValue(): Enum1 {}
public set defaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2>,) {}
public setDefaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2>,): this { this.defaultValue = value; return this }
public get values(): CollectionHolder<Enum1> {}
public get names(): CollectionHolder<NameOf<Enum1>> {}
public get ordinals(): CollectionHolder<OrdinalOf<Enum1>> {}
public get iterator(): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public getValue(value: PossibleEnumerableValue<| Enum1 | Enum2>,): Enum1 {}
public getName(value: PossibleEnumerableValue<| Enum1 | Enum2>,): NameOf<Enum1> {}
public getOrdinal(value: PossibleEnumerableValue<| Enum1 | Enum2>,): OrdinalOr<Enum1> {}
public [Symbol.iterator](): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public get [Symbol.toStringTag](): CompanionEnumName { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithGrandParent (simplest)
import {CompanionEnumWithGrandParent} from "@joookiwi/enumerable"
class CustomCompanionEnum
extends CompanionEnumWithGrandParent<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2, // parent
Enum3, typeof Enum3> { // grand-parent
constructor() { super(Enum1, Enum2, Enum3,) }
}
CompanionEnumWithGrandParentDeclaration (hardest, but fully customizable)
import type {CollectionHolder, CollectionIterator} from "@joookiwi/collection"
import type {CompanionEnumWithGrandParentDeclaration, CompanionEnumName,
NameOf, Nullable, OrdinalOf, PossibleEnumerableValue} from "@joookiwi/enumerable"
class CustomCompanionEnum
implements CompanionEnumWithGrandParentDeclaration<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2, // parent
Enum3, typeof Enum3> { // grand-parent
readonly #instance
readonly #parentInstance
readonly #grandParentInstance
protected constructor() {
this.#instance = Enum1
this.#parentInstance = Enum2
this.#grandParentInstance = Enum3
}
public get instance(): typeof Enum1 { return this.#instance }
public get parentInstance(): typeof Enum2 { return this.#parentInstance }
public get grandParentInstance(): typeof Enum3 { return this.#grandParentInstance }
public get defaultValue(): Enum1 {}
public set defaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3>,) {}
public setDefaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3>,): this { this.defaultValue = value; return this }
public get values(): CollectionHolder<Enum1> {}
public get names(): CollectionHolder<NameOf<Enum1>> {}
public get ordinals(): CollectionHolder<OrdinalOf<Enum1>> {}
public get iterator(): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public getValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3>,): Enum1 {}
public getName(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3>,): NameOf<Enum1> {}
public getOrdinal(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3>,): OrdinalOf<Enum1> {}
public [Symbol.iterator](): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public get [Symbol.toStringTag](): CompanionEnumName { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
CompanionEnumWithGreatGrandParent (simplest)
import {CompanionEnumWithGreatGrandParent} from "@joookiwi/enumerable"
class CustomCompanionEnum
extends CompanionEnumWithGreatGrandParent<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2, // parent
Enum3, typeof Enum3, // grand-parent
Enum4, typeof Enum4> { // great-grandparent
protected constructor() { super (Enum1, Enum2, Enum3, Enum4,)}
}
CompanionEnumWithGreatGrandParentDeclaration (hardest, but fully customizable)
import type {CollectionHolder, CollectionIterator} from "@joookiwi/collection"
import type {CompanionEnumWithGreatGrandParentDeclaration, CompanionEnumName, NameOf, Nullable, OrdinalOf, PossibleEnumerableValue} from "@joookiwi/enumerable"
class CustomCompanionEnum
implements CompanionEnumWithGreatGrandParent<
Enum1, typeof Enum1, // enum
Enum2, typeof Enum2, // parent
Enum3, typeof Enum3, // grand-parent
Enum4, typeof Enum4> { // great-grandparent
readonly #instance
readonly #parentInstance
readonly #grandParentInstance
readonly #greatGrandParentInstance
protected constructor() {
this.#instance = Enum1
this.#parentInstance = Enum2
this.#grandParentInstance = Enum3
this.#greatGrandParentInstance = Enum4
}
public get instance(): typeof Enum1 { return this.#instance }
public get parentInstance(): typeof Enum2 { return this.#parentInstance }
public get grandParentInstance(): typeof Enum3 { return this.#grandParentInstance }
public get greatGrandParentInstance(): typeof Enum4 { return this.#greatGrandParentInstance }
public get defaultValue(): Enum1 {}
public set defaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3 | Enum4>,) {}
public setDefaultValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3 | Enum4>,): this { this.defaultValue = value; return this }
public get values(): CollectionHolder<Enum1> {}
public get names(): CollectionHolder<NameOf<Enum1>> {}
public get ordinals(): CollectionHolder<OrdinalOf<Enum1>> {}
public get iterator(): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public getValue(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3 | Enum4>,): Enum1 {}
public getName(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3 | Enum4>,): NameOf<Enum1> {}
public getOrdinal(value: PossibleEnumerableValue<| Enum1 | Enum2 | Enum3 | Enum4>,): OrdinalOf<Enum1> {}
public [Symbol.iterator](): CollectionIterator<Enum1> { return this.values[Symbol.iterator]() }
public get [Symbol.toStringTag](): CompanionEnumName { return "CompanionEnum" /* or EnumConstants.COMPANION_ENUM_TO_STRING_TAG */ }
}
The "inheritance" is only dependent on the ordering of the constructors received in the companion enum class.
So, by reversing the ordering, then the implementation is correctly used.
Use super(ChildEnum, ParentEnum,)
instead of super(ParentEnum, ChildEnum,)
Javascript
Change the implementation from:
class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
constructor() { super(ParentEnum, ChildEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
to
class CompanionEnum_ChildEnum extends CompanionEnumWithParent {
static #instance
constructor() { super(ChildEnum, ParentEnum,) }
static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
Typescript
Change the implementation from:
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ParentEnum, typeof ParentEnum, ChildEnum, typeof ChildEnum> {
static #instance?: CompanionEnum_ChildEnum
private constructor() { super(ParentEnum, ChildEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
to
class CompanionEnum_ChildEnum extends CompanionEnumWithParent<ChildEnum, typeof ChildEnum, ParentEnum, typeof ParentEnum> {
static #instance?: CompanionEnum_ChildEnum
private constructor() { super(ChildEnum, ParentEnum,) }
public static get get() { return CompanionEnum_ChildEnum.#instance ??= new CompanionEnum_ChildEnum() }
}
In Typescript
, it can be possible to have an error even though, it cannot be one in Javascript
.
By declaring a class onto a field, then, the type inference would not work properly if it has a reference of itself.
That is why every companion enum has a singleton
type declaration.
// Bad example
class Example extends Enum {
// ts-error: Field cannot infer the type
public static readonly Field = class NestedExample {
field = Example
}
}
// Correct example
class Example extends Enum {
public static readonly Field: NestedExampleDeclaration<typeof Example> = class NestedExample {
readonly field = Example
}
}
interface NestedExampleDeclaration<T> {
readonly field: T
}
Maybe this method did throw you something like
NullReferenceException: No Enumerable-like could be found from the prototype chain "EnumLike → EnumLike → Object".
This is likely due to having one requirement (ordinal
, name
, Symbol.toPrimitive
or Symbol.toStringTag
)
set as a field instead of a method (or getter method).
The values are not expected to change,
but it is expected to have at least one class with everything the Enumerable
have.
A simple change can be done from:
Javascript (by fields)
class EnumLike {
constructor() {
this.ordinal = someOrdinalCode
this.name = someNameCode
this[Symbol.toPrimitive] = () => someToPrimitiveCode
this[Symbol.toStringTag] = "Enum"
}
}
to be transformed to
class EnumLike {
#ordinal
#name
constructor() {
this.#ordinal = someOrdinalCode
this.#name = someNameCode
}
get ordinal() { return this.#ordinal }
get name() { return this.#name }
[Symbol.toPrimitive]() { return somePrimitiveCode }
get [Symbol.toStringTag]() { return "Enum" }
}
Javascript (by constructor default value)
class EnumLike {
constructor(ordinal = someOrdinalCode, name = someNameCode){
this.ordinal = ordinal
this.name = ordinal
this[Symbol.toPrimitive] = () => someToPrimitiveCode
this[Symbol.toStringTag] = "Enum"
}
}
to be transformed to
class EnumLike {
#ordinal
#name
constructor(ordinal = someOrdinalCode, name = someNameCode) {
this.#ordinal = ordinal
this.#name = name
}
get ordinal() { return this.#ordinal }
get name() { return this.#name }
[Symbol.toPrimitive]() { return somePrimitiveCode }
get [Symbol.toStringTag]() { return "Enum" }
}
Typescript (by simple fields)
class EnumLike {
public readonly ordinal = someOrdinalCode
public readonly name = someNameCode
public readonly [Symbol.toPrimitive] = () => someToPrimitiveCode
public readonly [Symbol.toStringTag] = "Enum"
}
to be transformed to
class EnumLike {
readonly #ordinal
readonly #name
constructor() {
this.#ordinal = someOrdinalCode
this.#name = someNameCode
}
public get ordinal() { return this.#ordinal }
public get name() { return this.#name }
public [Symbol.toPrimitive]() { return somePrimitiveCode }
public get [Symbol.toStringTag]() { return "Enum" as const }
}
Typescript (by constructor initialization fields)
class EnumLike {
public readonly [Symbol.toPrimitive] = () => someToPrimitiveCode
public readonly [Symbol.toStringTag] = "Enum"
constructor(public readonly ordinal = someOrdinalCode,
public readonly name = someNameCode,){}
}
to be transformed to
class EnumLike {
readonly #ordinal
readonly #name
constructor(ordinal = someOrdinalCode,
name = someNameCode,) {
this.#ordinal = ordinal
this.#name = name
}
public get ordinal() { return this.#ordinal }
public get name() { return this.#name }
public [Symbol.toPrimitive]() { return somePrimitiveCode }
public get [Symbol.toStringTag]() { return "Enum" as const }
}
There is a known error for the optional index type being set on an Enum on Typescript exclusively. Currently, it is unknown where it is located, but just commenting the type resolve the thing. An alternative to it is to put the optional types over the declared constants.
// Known error
class ChildEnum {
public static readonly A = new ChildEnum()
public static readonly 0: typeof ChildEnum.A
}
// ChildEnum.A is fine
// ChildEnum[0] is always being set to undefined
// Solution 1
class ChildEnum {
public static readonly A = new ChildEnum()
// public static readonly 0: typeof ChildEnum.A
}
// ChildEnum.A is fine
// ChildEnum[0] is fine
// Solution 2
class ChildEnum {
public static readonly 0: typeof ChildEnum.A
public static readonly A = new ChildEnum()
}
// ChildEnum.A is fine
// ChildEnum[0] is fine
You can contribute to the project in 2 different ways: