Open qc00 opened 9 years ago
Indeed, it could save lots of copy-paste code, e.g. when making string <--> enum conversions which is a strong industrial case.
Now I do this a lot:
enum AnimalType {
Cat,
Dog,
Invalid
}
module AnimalType {
export function parse(str:string):AnimalType {
switch(type) {
case 'cat': return AnimalType.Cat;
case 'dog': return AnimalType.Dog;
default: return AnimalType.Invalid;
}
}
export function toString(type: AnimalType): string { /* ... */ }
}
How nice would this be:
enum AnimalType {
@parse('cat')
Cat,
@parse('dog')
Dog,
@parseDefault('invalid') /* parses everything, toString returns 'invalid' */
Invalid
}
@igabesz can you explain how parse
would be implemented? what does it return?
I'm thinking of something like the C# DisplayName annotation. The main point is that @parse stores the string given to it; this string can be retrieved somehow through some metadata. The rest of the string-to-enum mapping should be implemented in a given function, but only once, not once per enum type.
I'm not very familiar with the current annotation syntax (btw any good and deep tutorials?), but I imagine something like this.
var AnimalType = (function(AnimalType) {
AnimalType = {
Cat = 0,
Dog = 1
}
// this is some annotation or decorator container
Object.defineProperty(AnimalType, '__decorators', {
enumerable: false,
configurable: false,
writable: true,
value: {} // or maybe a Set?
});
// Something like this should be auto-generated
// Can be in a different format, e.g. AnimalType and value could be passed too
AnimalType.__decorators[AnimalType.Dog] = [ new parse('dog') ];
AnimalType.__decorators[AnimalType.Cat] = [ new parse('cat') ];
return AnimalType;
}) (AnimalType || {});
// Defining annotation (just the relevant part)
function parse(str) {
this.__annotationName = 'parse';
this.str = str;
}
// One must implement these two functions by hand
// But they are general so they can be used with any enums
function printEnum(enumType, value) {
var annotations = enumType.__decorators[value];
var parseAnnotation = getParseFromList(annotations);
return parseAnnotation.str;
}
function readToEnum(enumType, str) {
var decorators = enumType.__decorators;
var value = selectEnumValueWhereTheParseAnnotationMatches(str);
return value;
}
This is significantly different behavior from what decorators mean for classes. this means that you can not take your knowledge of writing a class /ES7 decorator to enums.
+1
+1
+1
+1 to being able to decorate enum properties just like the props of any other object
+1
👍 We definitely need decorators for enum members.
Any update on this?
+1
+1
+1
+1
Currently TypeScript implements an older and now obsolete version of the ES Decorator proposal. The TypeScript Roadmap mentions the implementation of the new syntax, however it is not scheduled yet. (Well, it seems to be a huge pain with lots of coordination and breaking changes.)
I guess if there is any progress then it should be according to the new decorator syntax for classes -- as much as it can be applied on enums. Any official word on this?
Definitely required
any update?
+1
+1 Would be great feature.
+1
Let's keep this one at the forefront.
Until the JS standard body has made some concrete decisions on what decorators should look and act like, we're unlikely to be adding new decorator features to TypeScript. Please don't add +1 comments unless you have something new to add.
There's a new, simpler proposal (again at stage2) for decorators - since when will you consider adding new features like this one? It could save us some boilerplate with graphql enum registering (but we'd need to somehow get the enum name).
I have 3 forms of using the next enum:
enum Foo {
bar,
daz
}
class Some {
foo: Foo = Foo.bar;
}
Some.foo
. So devs can do some.foo == Foo.bar
query {
foo
}
The above should result in 'bar'
If I add a value to the enum, ie enum Foo { bar = 1 }
then frontend devs that uses the result of a graphql fetch can't do some.foo == Foo.bar
because some.foo
, that comes from graphql, would be 'bar'
and not 1
.
So the best option to us would be:
enum Foo {
@val(1)
bar,
@val(2)
daz
}
so the values of the enums would only be used in the database.
some one may need this code:
export class Enum extends Number {
private static ___value_to_key___: any = {}
private static ___value_to_info___: any = {}
static valueToKey(value: any) {
return this.___value_to_key___[value]
}
static valueToInfo(value: any) {
return this.___value_to_info___[value]
}
}
export function AddInfo(info: any) {
return (a_enum_class: any | Enum, key: any) => {
const value = a_enum_class[key];
a_enum_class.___value_to_key___[value] = key;
a_enum_class.___value_to_info___[value] = info;
}
}
export class FooEnum extends Enum {
@AddInfo('一') static one = 1;
@AddInfo('二') static two = 2;
@AddInfo('三') static three = 3;
}
https://github.com/poerlang/typescript-enum-class-decorators
some other code ( how to use the FooEnum / Enum )
let theType: FooEnum = FooEnum.three; // set a enum
if (theType === FooEnum.one) console.log('yes') // use Enum in if
FooEnum.one // get value
FooEnum.valueToKey(FooEnum.one) // get key
FooEnum.valueToInfo(FooEnum.one) // get info
Note: It is necessary to add the setting in tsconfig.json:
{
"compilerOptions": {
"experimentalDecorators": true,
... // other setting
}
}
Until the JS standard body has made some concrete decisions on what decorators should look and act like, we're unlikely to be adding new decorator features to TypeScript. Please don't add +1 comments unless you have something new to add.
How long would we wait until the JS standard body has made some concrete decisions before TypeScript implements this? It's been 8 years now, maybe at 10 years? :)
I'm also a little confused on why we are waiting on the JS standard body. Aren't enums a TypeScript concept anyway?
What if this came via an experimental version or something that lets people know that we can use it, but may break in the future?
+1
If folks just want this for parsing, why not ask for a parser, that seems to be such a standard use case, but such a headache to handle typing properly without casting something along the way.
any update for this?
It would be nice to be able to decorate enum members (in the same way as properties?).