-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactors enum to enable calling like a factory function.
- Loading branch information
1 parent
6c1d270
commit 7b7df53
Showing
4 changed files
with
75 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,34 @@ | ||
import { Counter, enumOf, Integers, Lowercased, Strings } from './enum-xyz.js' | ||
import { enumOf, Integers, Lowercased, Strings } from './enum-xyz.js' | ||
|
||
/** @type {import("./types").deprecated} */ | ||
const deprecated = ({ from, to, using }) => | ||
enumOf( | ||
(name) => ( | ||
console.warn(`\`${from}\` is deprecated; use \`${to}\` instead`), | ||
using[name] | ||
) | ||
) | ||
/** | ||
* @template T | ||
* @param {import("./types").Enum<T>} replacement | ||
* @param {string} warning | ||
*/ | ||
const deprecated = (replacement, warning) => | ||
enumOf((name) => (console.warn(warning), replacement[name])) | ||
|
||
/** @deprecated */ | ||
export const String = deprecated({ | ||
from: 'String', | ||
to: 'Strings', | ||
using: Strings, | ||
}) | ||
|
||
export const String = deprecated( | ||
Strings, | ||
'`String` is deprecated; use `Strings` (plural) instead' | ||
) | ||
/** @deprecated */ | ||
export const StringLower = deprecated({ | ||
from: 'StringLower', | ||
to: 'Lowercased', | ||
using: Lowercased, | ||
}) | ||
|
||
export const StringLower = deprecated( | ||
Lowercased, | ||
'`StringLower` is deprecated; use `Lowercased` instead' | ||
) | ||
/** @deprecated */ | ||
export const Numeric = deprecated({ | ||
from: 'Numeric', | ||
to: 'Integers', | ||
using: Integers, | ||
}) | ||
|
||
export const Numeric = deprecated( | ||
Integers, | ||
'`Numeric` is deprecated; use `Integers` instead' | ||
) | ||
/** | ||
* @deprecated | ||
* @param {number} startIndex | ||
* @param {number} start | ||
*/ | ||
export const NumericAt = (startIndex) => | ||
deprecated({ | ||
from: 'NumericAt', | ||
to: 'Counter', | ||
using: Counter(startIndex), | ||
}) | ||
export const NumericAt = (start) => | ||
deprecated( | ||
Integers(start), | ||
'`NumericAt()` is deprecated; use `Integers()` instead' | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,38 @@ | ||
/** | ||
* @type {import("./types").enumOf} | ||
* @param mapper should return the same value for the same name | ||
*/ | ||
export const enumOf = (mapper, state) => | ||
new Proxy( | ||
{}, | ||
{ | ||
// @ts-ignore | ||
get: (_, name) => mapper(name, state), | ||
} | ||
) | ||
/** @type {import("./types").enumOf} */ | ||
export const enumOf = (getter) => { | ||
const handler = getter instanceof Function ? { get: getter } : getter, | ||
{ get, apply } = handler | ||
// must target function to be callable | ||
return new Proxy(apply ? () => {} : {}, { | ||
...handler, | ||
get: (_, /** @type {string} */ name) => get(name), | ||
apply: | ||
apply && ((_, _1, /** @type {any} */ args) => apply(handler, ...args)), | ||
}) | ||
} | ||
|
||
/** | ||
* @type {import("./types").memoEnumOf} | ||
* @param mapper always returns the same value for the same name | ||
*/ | ||
export const memoEnumOf = (mapper) => | ||
enumOf( | ||
(name, map) => map.get(name) ?? map.set(name, mapper(name)).get(name), | ||
new Map() | ||
) | ||
/** @type {import("./types").memoEnumOf} */ | ||
export const memoEnumOf = (getter) => { | ||
const handler = getter instanceof Function ? { get: getter } : getter, | ||
cache = new Map() | ||
return enumOf({ | ||
...handler, | ||
get: (name) => | ||
cache.get(name) ?? cache.set(name, handler.get(name)).get(name), | ||
}) | ||
} | ||
|
||
export const Strings = enumOf((name) => name) | ||
|
||
export const Lowercased = enumOf((name) => name.toLowerCase()) | ||
|
||
export const Symbols = memoEnumOf(Symbol) | ||
export const Symbols = enumOf({ | ||
get: Symbol.for, | ||
apply: () => enumOf(Symbol), | ||
}) | ||
|
||
export const Counter = (startIndex = 0) => memoEnumOf((name) => startIndex++) | ||
|
||
export const Integers = Counter() | ||
let nextInteger = 0 | ||
export const Integers = memoEnumOf({ | ||
get: () => nextInteger++, | ||
apply: (_, start = 0) => enumOf(() => start++), | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
export * from './enum-xyz.js' | ||
export * from './deprecated.js' | ||
// don't re-export extras | ||
// re-export types | ||
/** @template T @typedef {import("./types").Enum<T>} Enum */ | ||
/** @template T @template {[] | [any]} [TArgs=[]] | ||
@typedef {import("./types").CallableEnum<T, TArgs>} CallableEnum */ | ||
/** @template T @typedef {import("./types").Strings<T>} Strings */ | ||
/** @template T @typedef {import("./types").Lowercased<T>} Lowercased */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters