Closed jhlange closed 7 years ago
@NN There are two issues, one minor, and one major:
The benefits of inlining are that the library could provide a set of named constants which could be used from Typescript, even though they might not exist / be accessible at runtime.
I lining is a general problem, it can be applied to everything.
@NN--- thanks for the link, very interesting. The only big difference between the technique you posted and an enum is that with the latter I can access the types as properties. As an example, this is how one would implement redux's actions in typescript:
export type INCREMENT_COUNTER = 'App/INCREMENT_COUNTER';
export const INCREMENT_COUNTER : INCREMENT_COUNTER = 'App/INCREMENT_COUNTER';
export type DECREMENT_COUNTER = 'App/DECREMENT_COUNTER';
export const DECREMENT_COUNTER : DECREMENT_COUNTER = 'App/DECREMENT_COUNTER';
export type IncrementCounterAction = {
type: INCREMENT_COUNTER,
by: number
};
export type DecrementCounterAction = {
type: DECREMENT_COUNTER,
by: number
};
type Action = IncrementCounterAction | DecrementCounterAction;
function reducer<S>(state: S, action: Action): S {
switch(action.type) {
case DECREMENT_COUNTER:
//action has .type & .by correctly detect by the compiler
}
}
The same code can be easily converted to enums:
enum Actions {
INCREMENT_COUNTER,
DECREMENT_COUNTER
}
export type IncrementCounterAction = {
type: Actions.INCREMENT_COUNTER,
by: number
};
export type DecrementCounterAction = {
type: Actions.DECREMENT_COUNTER,
by: number
};
type Action = IncrementCounterAction | DecrementCounterAction;
function reducer<S>(state: S, action: Action): S {
switch(action.type) {
case Actions.DECREMENT_COUNTER:
//action has .type & .by correctly detect by the compiler
}
}
but it falls short when I use the workaround:
export const Actions = {
INCREMENT_COUNTER: 'INCREMENT_COUNTER' as 'INCREMENT_COUNTER',
DECREMENT_COUNTER: 'DECREMENT_COUNTER' as 'DECREMENT_COUNTER'
}
export type Actions = (typeof Actions)[keyof typeof Actions];
export type IncrementCounterAction = {
type: Actions.INCREMENT_COUNTER, // ERROR. no way to get type INCREMENT_COUNTER
by: number
};
export type DecrementCounterAction = {
type: Actions.DECREMENT_COUNTER, // ERROR. no way to get type DECREMENT_COUNTER
by: number
};
type Action = IncrementCounterAction | DecrementCounterAction;
function reducer<S>(state: S, action: Action): S {
switch(action.type) {
case Actions.DECREMENT_COUNTER:
//action has .type & .by correctly detect by the compiler
}
}
@danielepolencic You may be interested in my solution using ngrx. Here's an issue I created in their repo about updating their sample for typescript 2.1+. It shows pre- and post- typescript 2.1+ versions using discriminated unions. TS 2.1+ introduced a breaking change (arguable a bug fix) regarding how string literals are handled.
Anyway, here's the ngrx issue about it, and here's a direct link to the typescript playground referenced in that issue.
@danielepolencic Instead of
export type IncrementCounterAction = {
type: Actions.INCREMENT_COUNTER, // ERROR. no way to get type INCREMENT_COUNTER
by: number
};
export type DecrementCounterAction = {
type: Actions.DECREMENT_COUNTER, // ERROR. no way to get type DECREMENT_COUNTER
by: number
};
try
export type IncrementCounterAction = {
type: typeof Actions.INCREMENT_COUNTER,
by: number
};
export type DecrementCounterAction = {
type: typeof Actions.DECREMENT_COUNTER,
by: number
};
@errorx666 @rob3c nice! thanks!
There still a lot of boiler plate, but it's definitely usable.
👍
Some discussion today. Unorganized notes; refer to https://github.com/Microsoft/TypeScript/issues/1206#issuecomment-240581743 for a mini-spec with some changes as follows
- Because of transpile, we can't detect string vs non-string enum by looking at the initializers
- This means all values would need to be exactly string literals
Would this restrict enums to just primitives (or even just number
/string
) - or would it be more widely applicable to any value (that exactly matches the enum's type)?
I don't think enums with values other than strings or numbers are on the table at this point. It's unclear what a const enum
with a reference type value would mean, and existing solutions (see https://github.com/Microsoft/TypeScript/issues/1206#issuecomment-225813145) seem to be doing pretty well. And we're definitely not adding boolean
enums :wink:
Makes sense
And we're definitely not adding boolean enums 😉
Pff, I swear there are totally legit reasons for
enum bool: boolean = {
true = false,
false = true,
};
Actually you can achieve that with
enum bool {
true = 0,
false = 1
}
Hah
On Tue, Apr 4, 2017 at 3:05 PM Daniel Busłowicz notifications@github.com wrote:
Actually you can achieve that with
enum bool { true = 0, false = 1 }
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Microsoft/TypeScript/issues/1206#issuecomment-291645840, or mute the thread https://github.com/notifications/unsubscribe-auth/AAChndeXT4OF-SiF0Vd16Au4nZcYIGh9ks5rsr6fgaJpZM4C9e4r .
@RyanCavanaugh Is it possible to allow reference type enums provided they aren't const enum
s? I don't see why every enum
type has to have a const enum
variant.
@nevir Don't forget FileNotFound.
@isiahmeadows it's possible, but it'd have to be well-justified because it's a lot more complexity. For a string
enum we can just produce a union type out of the literal types of its values, but there's no corresponding behavior for reference types because there's no such thing as a literal type for a reference type value.
@RyanCavanaugh Oh, I see now, and it's not really a short term need for me.
Maybe, in the future, could nominal subtyping could help?
In my scenario I needed sort of custom object enum, since my class does not have any method that would make the inheritance necessary, I just used this class with static props:
export class ViewerItemCardType {
public static Big: ViewerItemCardType = new ViewerItemCardType(1, "FeaturedBig", 330, 660);
public static Medium: ViewerItemCardType = new ViewerItemCardType(2, "FeaturedSmall", 155, 310);
public static Small: ViewerItemCardType = new ViewerItemCardType(3, "NormalArticle", 100, 200);
private constructor(
public id: number,
public name: string,
public imageHeight: number,
public imageWidth: number
) { };
}
I can access to these "complex" enums like:
ViewerItemCardType.Big.imageHeight
ViewerItemCardType.Big
ViewerItemCardType.Small
@isiahmeadows , Does that particular scenario match with your definition at some point ?
@jquintozamora that's awesome!
I think you can infer the extra type-hints though, and you'd likely want to define a means of enumerating the options as well, depending on your use-case - so like:
export class ViewerItemCardType {
public static Big = new ViewerItemCardType(1, "FeaturedBig", 330, 660);
public static Medium = new ViewerItemCardType(2, "FeaturedSmall", 155, 310);
public static Small = new ViewerItemCardType(3, "NormalArticle", 100, 200);
public static All: ViewerItemCardType[] = [
ViewerItemCardType.Big,
ViewerItemCardType.Medium,
ViewerItemCardType.Small
]
private constructor(
public id: number,
public name: string,
public imageHeight: number,
public imageWidth: number
) { };
}
@jquintozamora also note that it's a closed set though - you can't use declaration merging to add new values, so that's another thing we'd (hopefully) get from real typed enums.
Hi @mindplay-dk , In my current scenario is really helpful when used in combitation with react - style attribute. Indeed, it would be good to have a official solution for that like real typed complex enums. :)
Implementation now available in #15486.
I released ts-enums as a library that enables creating full-class, Java-style enums. Maybe it can be useful for some people on this thread.
Suggestions for improvements are welcome :)
With Angular 2 //enum
export enum IType
{
Vegitable=0,
Fruits=1,
Fish=2
}
// angular 2 Component in type script
import {IType} from '/itype';
export class DataComponent
{
getType(id:number):any
{
return IType[id];
}
}
// in your html file
<div>
{{getType(1)}}
</div>
I'm reopening this issue, because it was closed with the move from codeplex, and doesn't seem to have been re-opened. https://typescript.codeplex.com/workitem/1217
I feel like this is very important for a scripting language.-- Especially for objects that are passed back and forth over web service calls.-- People generally don't use integer based enums in json objects that are sent over the wire, which limits the usefulness of the current enum implementation quite a bit.
I would like to re-propose the original contributor's suggestions verbatim.