I want symbol enum.
syntax example:
symbol enum Example{
X,Y,Z
}
↓
var Example;
(function (Example) {
Example[Example["X"] = new Symbol("X")] = "X";
Example[Example["Y"] = new Symbol("Y")] = "Y";
Example[Example["Z"] = new Symbol("Z")] = "Z";
})(Example || (Example = {}));
We first need a way to treat symbol
s as literals, just like string and numeric literals. this is covered in https://github.com/Microsoft/TypeScript/pull/15473
I see #15473 merged, does it mean we can use Symbols in Enum somehow?
I want to use Enum with the Types: string, number or Symbol.
Not to bikeshed, but wouldn't a more consistent syntax be:
enum Example: Symbol {
X,Y,Z
}
// or
enum Example<Symbol> {
X,Y,Z
}
Rather than introducing a new keyword of symbol
these options either use inheritance style, or Generics, and would pave the way for arbitrary-valued enums?
This would be very useful with Redux actions...
Is there something that would help move this issue?
If it would just be making a PR at this point I might be able to do it, may need to be guided in the right direction to start.
I've found an alternative way to do it, and I hope it helps:
/**
* Action types for StoreState.todo
*/
export namespace TodoActionTypes {
// Adding todo item
export const ADD_ITEM = Symbol('@todo/ADD_ITEM')
export type ADD_ITEM = typeof ADD_ITEM
// Removing todo item
export const DEL_ITEM = Symbol('@todo/DEL_ITEM')
export type DEL_ITEM = typeof DEL_ITEM
// Performing undo on StoreState.todo
export const UNDO = Symbol('@todo/UNDO')
export type UNDO = typeof UNDO
// Performing redo on StoreState.todo
export const REDO = Symbol('@todo/REDO')
export type REDO = typeof REDO
}
/**
* Action types for StoreState.todo
*/
export type TodoActionTypes =
| TodoActionTypes.ADD_ITEM
| TodoActionTypes.DEL_ITEM
| TodoActionTypes.UNDO
| TodoActionTypes.REDO
I've found an alternative way to do it, and I hope it helps:
/** * Action types for StoreState.todo */ export namespace TodoActionTypes { // Adding todo item export const ADD_ITEM = Symbol('@todo/ADD_ITEM') export type ADD_ITEM = typeof ADD_ITEM // Removing todo item export const DEL_ITEM = Symbol('@todo/DEL_ITEM') export type DEL_ITEM = typeof DEL_ITEM // Performing undo on StoreState.todo export const UNDO = Symbol('@todo/UNDO') export type UNDO = typeof UNDO // Performing redo on StoreState.todo export const REDO = Symbol('@todo/REDO') export type REDO = typeof REDO } /** * Action types for StoreState.todo */ export type TodoActionTypes = | TodoActionTypes.ADD_ITEM | TodoActionTypes.DEL_ITEM | TodoActionTypes.UNDO | TodoActionTypes.REDO
i guess this will do?
export type TodoActionTypes =
| ADD_ITEM
| DEL_ITEM
| UNDO
| REDO
I have found another solution at https://fettblog.eu/symbols-in-javascript-and-typescript/ and I slightly improved it. Sadly, there is lot of code around it, but it gives pretty protection (compile time and runtime)
const COLOR_RED = Symbol('COLOR_RED');
const COLOR_ORANGE = Symbol('COLOR_ORANGE');
// intentionally not part of the enum for demonstration
const COLOR_GREEN = Symbol('COLOR_GREEN');
// freeze needed for runtime protection
export const colors = Object.freeze({
COLOR_RED,
COLOR_ORANGE,
} as const);
type ValuesWithKeys<T, K extends keyof T> = T[K];
type Values<T> = ValuesWithKeys<T, keyof T>
export type COLOR = Values<typeof colors>;
function foo(val: COLOR) {
}
foo(COLOR_RED);
foo(colors.COLOR_ORANGE);
foo(COLOR_GREEN); // refused by typescript
Most helpful comment
Not to bikeshed, but wouldn't a more consistent syntax be:
Rather than introducing a new keyword of
symbol
these options either use inheritance style, or Generics, and would pave the way for arbitrary-valued enums?