-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Different keys and values #5
Comments
Hi onury, Unfortunately I haven't found a good way to do this. All my attempts have failed because the only way I know of to produce a type that TypeScript understands as an object with string literal values that are different from its keys is to write one yourself by hand. So you may be forced to write the following, which works: const Status = {
RUNNING: "running" as "running",
STOPPED: "stopped" as "stopped"
}; There is another option that I toyed with a bit: export function WeirdEnum<K extends string>(object: { [key: K]: string }): { [k in K]: k } {
return object as any;
}
export type WeirdEnum<T> = T[keyof T]; then use it as export const Status = WeirdEnum({
RUNNING: "running",
STOPPED: "stopped"
});
export type Status = WeirdEnum<typeof Status>;
console.log(Status.RUNNING); // -> "running"
// Enum can be used for discriminated unions:
type State = RunningState | StoppedState;
interface RunningState {
status: typeof Status.RUNNING;
pid: number;
}
interface StoppedState {
status: typeof Status.STOPPED;
shutdownTime: Date;
}
function saySomethingAboutState(state: State) {
// The following typechecks.
if (state.status === Status.RUNNING) {
console.log("The pid is " + state.pid);
} else if (state.status === Status.STOPPED) {
console.log("The shutdown time is " + state.shutdownTime);
}
} So this works, in a way. The issue is that even though const status: Status = "running"; // Type error: "running" not assignable to type "RUNNING" | "STOPPED". I decided not to include this in this project because I feel like lying to TypeScript like this is a pretty sketchy thing to do, but it is there as an option if you think it's worth it. I would be pretty happy to see if someone can come up with a better solution. |
@dphilipson, thanks for the detailed answer. {
RUNNING: 'running',
STOPPED: 'stopped',
running: 'running',
stopped: 'stopped'
} |
@onury, oh I'm really sorry, I somehow missed that you had responded to this thread. I apologize for the really slow response. Can you elaborate a bit on the question? Is that snippet something that you would like to be able to express using the library, or a proposed solution to the problems in the previous post? |
No problem at all. Correction: You could auto-assign the values. {
RUNNING: 'running',
STOPPED: 'stopped'
} You auto-assign the values as keys, if they're different: {
RUNNING: 'running',
STOPPED: 'stopped',
running: 'running',
stopped: 'stopped'
} |
Another example: {
SERVER_ERROR: 'ServerError',
CLIENT_ERROR: 'client:error'
} auto-generate: {
SERVER_ERROR: 'ServerError',
CLIENT_ERROR: 'client:error',
ServerError: 'ServerError',
'client:error': 'client:error'
} |
Ah, interesting idea. I'm not sure offhand how to express that through the type system (writing the function signature is the hard part), but I'll experiment. This does have a few drawbacks I assume would come up if you managed to nail down the type signature:
const status: Status = "RUNNING"; // Typechecks, even though it shouldn't.
|
You're right. This would be very hacky. |
This can now be done in 0.2.0 with the new object syntax. The following now works: export const Status = Enum({
/**
* Everything is fine.
*
* Hovering over Status.RUNNING in an IDE will show this comment.
*/
RUNNING: "running",
/**
* All is lost.
*/
STOPPED: "stopped",
});
export type Status = Enum<typeof Status>;
console.log(Status.RUNNING); // -> "running" |
How would I get an enum having different keys and values like this:
so I can do:
The text was updated successfully, but these errors were encountered: