03:56 | <Jack Works> | i'd love to see some examples that feel javascripty I'll show some code I found in our product source. You may argue TypeScript is not javascripty but it's a big part you cannot unsee in the JS community
type Action =
| { type: 'SET_ACCOUNT_TYPE', accountType: BackupAccountType }
| { type: 'TO_STEP', step: RestoreStep }
| { type: 'SET_EMAIL', form: Partial<RestoreState['emailForm']> }
| { type: 'SET_PHONE', form: Partial<RestoreState['phoneForm']> }
| { type: 'SET_VALIDATION' }
| { type: 'SET_BACKUP_INFO', info: BackupFileInfo }
| { type: 'SET_BACKUP_SUMMARY', summary: BackupSummary, backupDecrypted: string }
| { type: 'SET_PASSWORD', password: string }
| { type: 'SET_LOADING', loading: boolean }
function restoreReducer(state: RestoreState, action: Action) {
return produce(state, (draft) => {
switch (action.type) {
case 'SET_ACCOUNT_TYPE':
// ...
case 'NEXT_STEP':
// ...
case 'TO_STEP':
// ...
}
})
}
dispatch({ type: 'SET_ACCOUNT_TYPE', accountType: 'email' })
|
03:56 | <Jack Works> | I wrote this pattern a lot. My co-workers also. |
03:57 | <ljharb> | nah TS code isn’t necessarily un-JavaScripty :-) not making that claim. |
03:57 | <ljharb> | so, that kind of switch usage is very common. That’s using a tagged union where the tag could be a primitive enum. |
03:58 | <Jack Works> | well, the important thing here is that the tag is always bind with a known-shaped structure |
03:59 | <Jack Works> | I'll rewrite this code with primitive enum and ADT enum |
04:02 | <Jack Works> | Primitive
enum Action {
SET_ACCOUNT_TYPE,
TO_STEP,
SET_EMAIL,
SET_PHONE,
SET_VALIDATION,
SET_BACKUP_INFO,
SET_BACKUP_SUMMARY,
SET_PASSWORD,
SET_LOADING,
}
type Action =
| { type: Action.SET_ACCOUNT_TYPE, accountType: BackupAccountType }
| { type: Action.TO_STEP, step: RestoreStep }
| { type: Action.SET_EMAIL, form: Partial<RestoreState['emailForm']> }
| { type: Action.SET_PHONE, form: Partial<RestoreState['phoneForm']> }
| { type: Action.SET_VALIDATION }
| { type: Action.SET_BACKUP_INFO, info: BackupFileInfo }
| { type: Action.SET_BACKUP_SUMMARY, summary: BackupSummary, backupDecrypted: string }
| { type: Action.SET_PASSWORD, password: string }
| { type: Action.SET_LOADING, loading: boolean }
function restoreReducer(state: RestoreState, action: Action) {
return produce(state, (draft) => {
match(action) {
when { type: Action.SET_ACCOUNT_TYPE, let accountType }: expr,
when { type: Action.SET_EMAIL, let form }: expr,
when { type: Action.TO_STEP, let step }: expr,
}
})
}
dispatch({ type: 'SET_ACCOUNT_TYPE', accountType: 'email' })
|
04:04 | <Jack Works> | ADT
enum Action {
SET_ACCOUNT_TYPE(accountType: BackupAccountType),
TO_STEP(step: RestoreStep),
SET_EMAIL(form: Partial<RestoreState['emailForm']>),
SET_PHONE(form: Partial<RestoreState['phoneForm']>),
SET_VALIDATION,
SET_BACKUP_INFO(info: BackupFileInfo),
SET_BACKUP_SUMMARY(summary: BackupSummary, backupDecrypted: string),
SET_PASSWORD(password: string),
SET_LOADING(loading: boolean),
}
function restoreReducer(state: RestoreState, action: Action) {
return produce(state, (draft) => {
match(action) {
when Action.SET_ACCOUNT_TYPE(let accountType): expr,
when Action.SET_EMAIL(let form): expr,
when Action.TO_STEP(let step): expr,
}
})
}
dispatch(Action.SET_ACCOUNT_TYPE('email'))
|
04:08 | <Jack Works> | adt can reduce a lot of redundant code in this pattern. make code more dense and let people write more semantic code |
04:12 | <ljharb> | What about that code requires the enum values to not be strings? |
04:13 | <Jack Works> | What about that code requires the enum values to not be strings? sorry can you rephrase? I did not understand the meaning |
04:14 | <ljharb> | i mean that seems like a nicer sugar for the non-enum version of the code - where the tags are still strings, just better typed. |
04:16 | <Jack Works> | yes, if we remove the typescript part, it looks like just a small syntax sugar (but also with all performance benefits that Ron mentioned) |
04:16 | <Jack Works> | with typescript this feature is a huge improve |
04:17 | <ljharb> | right, and I’m super on board for that. but i don’t see what “adt” adds there nor why enum values need to be objects |
04:17 | <ljharb> | every enum proposal so far has satisfied that code’s need, which is a good thing |
16:44 | <ljharb> | (note: there was a typo in the TOC, but then i realized having a TOC is redundant because github auto-makes one on every markdown file, so i removed it) |