Makuhari Development Corporation
3 min read, 467 words, last updated: 2020/3/1
TwitterLinkedInFacebookEmail

Define Flat Constants

There are always situations that need us to define a list of values/relationships, like dropdown options, possible return values, etc.

Since we are using Typescript as a default consideration, there is always the requirement to use those constant types safely.

as const

The first attempt made years ago, was to define the list using as const

export const CARD_TYPE = [
  { attr: 'text', label: 'テキスト', formatter: ... }, 
  { attr: 'date', label: '日期選択', formatter: ... }
] as const;
 
const cardTypeList = CARD_TYPE.map(x => x.type);
export type CardType = typeof cardTypeList[number];

Here the CardType is equivalent to the definition below

type CardType = 'text' | 'date'

In this way, not only define a list of constants, but we could also generate the Union Type for that constants in the same place to use later.

const [cardType, setCardType] = useState<CardType>('text');

However, since we still need to touch everywhere if we want to change the text to something like textbook, which leads us to come to enums

enum

We quickly came to the thought that it's not incompatible with what we have done before, to put the definition of both types and constants together.

export enum CardType {
  TEXT = 'text',
  DATE = 'date',
}
export const cardList = [
  { label: 'テキスト', value: CardType.TEXT, formatter: ... },
  { label: '日期選択', value: CardType.DATE, formatter: ... },
]

flat structure

So far we have a general approach to defining constants with types. What about tree structure constants? For example, when we use some form libs like react-hook-form, if the conditional attributes grow, we may need to define the init form config constant using a tree structure.

One option to achieve it is flat/un-flat them all. We can still define the constants using a flat structure, combining them together, doing the validation under the flat structure, and submitting after un-flat. We can use some of the libs like flat to help us do that.

export const basicInfoForm: Array<FormItem> = [
  {
    label: '属性',
    value: BasicInfoForm.TYPE,
    form: Yup.number().required(),
    type: FormItemType.SELECT,
    option: InputTypeOption,
    formatter: acquireFromOptions(InputTypeOption)
  },
  {
    label: '関係',
    value: BasicInfoForm.RELATION,
    form: Yup.string().required().max(150),
    type: FormItemType.INPUT,
  },
  ...
];

There are always Pros & Cons doing that, sometimes it's a quick solution but we need to pay much attention cause it could go uncontrollable while the requirement changes!

Pros

  • validation error check goes extremely easy
  • conditionally removing part of the input fields corssing Objects is also directly handlable via filters

Cons

  • complex conditional form based on the dependencies cross entier form leads to uncontrollable complexity if using only flat structure
  • type-safe middle object attribute leads to ugly codes
Makuhari Development Corporation
法人番号: 6040001134259
サイトマップ
ご利用にあたって
個人情報保護方針
個人情報取扱に関する同意事項
お問い合わせ
Copyright© Makuhari Development Corporation. All Rights Reserved.