Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use/define Enums with Flow type checking?

Tags:

I'm trying to migrate an existing codebase to use Flow. Since this project started without Flow, I'm using a pretty typical JS pattern for enums and such.

Here are a few definitions I want to

export const LOAN_STATUS  = {   PENDING: 'pending',   CURRENT: 'current',   DUE: 'due',   OVERDUE: 'overdue',   PENDING_PAYMENT: 'pending_payment',   CHARGED_OFF: 'charged_off',   VOIDED: 'voided',   DISPUTED: 'disputed',   REFUNDED: 'refunded',   SETTLED: 'settled', }  export const ACTIVE_LOAN_STATUS = [   LOAN_STATUS.OVERDUE,   LOAN_STATUS.CURRENT,   LOAN_STATUS.DUE,   LOAN_STATUS.PENDING_PAYMENT, ] 

Flow works fine until I import this file and it says I need to add type annotations. This seems odd -- why should I have to annotate objects that are entirely static and easily inferred?

Is there any way that define its type as "static" or "literal"?

So then I go about thinking how I'm going to add annotations to this. My first thought is just {[key: string]: string} and Array<string>. Flow works, but I'm realizing that these type definitions are totally worthless. So then I try this other approach:

type LoanStatusValues =   'pending' |   'current' |   'due' |   'overdue' |   'pending_payment' |   'charged_off' |   'voided' |   'disputed' |   'refunded' |   'settled'  type LoanStatusKeys =   'PENDING' |   'CURRENT' |   'DUE' |   'OVERDUE' |   'PENDING_PAYMENT' |   'CHARGED_OFF' |   'VOIDED' |   'DISPUTED' |   'REFUNDED' |   'SETTLED'  type ActiveLoanStatus =  "current" | "due" | "overdue" | "pending_payment" 

And I use the type annotations {[key: LoanStatusKeys]: LoanStatusValues} and Array<ActiveLoanStatus>. But even these annotations loose the fact that this is static!

It just seems so odd that I'm having to write this much duplicate code. And then if I want to convert just to Flow I can't actually use the types in JS. For example I might do this:

if (defs.ACTIVE_LOAN_STATUS.indexOf(loan.status) !== -1) {  } 

Now if I want to use Flow types, I can't do anything like this:

type ActiveLoanStatus =    "current" |   "due" |   "overdue" |   "pending_payment"  if (loan.status isTypeOf ActiveLoanStatus) {  } 

So how am I supposed to use these static enums? I must be doing this wrong!

like image 262
Chet Avatar asked Aug 25 '16 21:08

Chet


People also ask

How do you define enum data type?

Enumeration or Enum in C is a special kind of data type defined by the user. It consists of constant integrals or integers that are given names by a user. The use of enum in C to name the integer values makes the entire program easy to learn, understand, and maintain by the same or even different programmer.

Where do you define enums?

The best way to define the enum is to declare it in header file. So, that you can use it anywhere you want by including that header file during compilation.

Can enums have user defined?

Enumeration (or enum) is a user defined data type in C. It is mainly used to assign names to integral constants, the names make a program easy to read and maintain.

Which data type can be used with enum?

The enum can be of any numeric data type such as byte, sbyte, short, ushort, int, uint, long, or ulong. However, an enum cannot be a string type.


1 Answers

To express an enum with flow you can use $Values utility in conjunction with frozen object type:

export const LOAN_STATUS = Object.freeze({   PENDING: 'pending',   CURRENT: 'current',   DUE: 'due',   OVERDUE: 'overdue',   PENDING_PAYMENT: 'pending_payment',   CHARGED_OFF: 'charged_off',   VOIDED: 'voided',   DISPUTED: 'disputed',   REFUNDED: 'refunded',   SETTLED: 'settled', });  type LoanStatus = $Values<typeof LOAN_STATUS>;  export const ACTIVE_LOAN_STATUS: LoanStatus[] = [   LOAN_STATUS.OVERDUE,   LOAN_STATUS.CURRENT,   LOAN_STATUS.DUE,   LOAN_STATUS.PENDING_PAYMENT, ] 

This works starting from 0.60.0 version.

like image 97
Aleksey L. Avatar answered Oct 14 '22 20:10

Aleksey L.