the-dr-lazy / deox

Functional Type-safe Flux Standard Utilities
https://deox.js.org
MIT License
206 stars 12 forks source link

Add isOfType helper #87

Closed nikolay-borzov closed 4 years ago

nikolay-borzov commented 5 years ago

Use case - a redux saga that is run when two actions dispatched, one with payload, other w/o payload

const fetchEntity = createActionCreator('FETCH', resolve => (id: string) => resolve(id));
const reFetchEntity = createActionCreator('RE_FETCH')

function* watchFetchEntity() {
  yield takeLastest([getType(fetchEntity), getType(reFetchEntity)], fetchEntitySaga);
}

function* fetchEntitySaga(action: ActionType<typeof fetchEntity> | ActionType<typeof reFetchEntity>) {
  const id = isOfType(getType(fetchEntity), action) 
    ? action.payload // id from fetchEntity
    : yield select(selectEntityId)
}
the-dr-lazy commented 5 years ago

Hey @nikolay-borzov, I'm not a redux-saga expert, but I think this problem should be solved in redux-saga. Give me time to read and search redux-saga documentation for this topic. So, if you have some links to guide me on this topic let me know. I will publish the results tomorrow.

nikolay-borzov commented 5 years ago

It's not only actual for sagas. Another case - handle action function that handles two actions with different payloads. In general any case when you need to infer action payload type from actions union type. I took isOfType idea from https://github.com/piotrwitek/typesafe-actions#isoftype

the-dr-lazy commented 5 years ago

The ofType RxJS operator uses the logic of isOfType helper so the logic can be extracted into the isOfType function and use by the ofType operator. I think the isOfType helper can accept multiple types of filtering inputs as how ofType do. The ofType operator accepts action creator(s), action(s), action type(s) as filtering inputs.

const a = createActionCreator('A')
const b = createActionCreator('B')

// With action creator
isOfType(a, a()) //=> true
isOfType(b, a()) //=> false
isOfType([a, b], a()) //=> true

// With action (object)
isOfType({ type: 'A' }, a()) //=> true
isOfType({ type: 'B' }, a()) //=> false
isOfType([{ type: 'A' }, { type: 'B' }], a()) //=> true

// With action type
isOfType('A', a()) // true
isOfType('B', a()) // false
isOfType(['A', 'B'], a()) // true

// Currying
isOfType (a) (a()) // true
isOfType ({ type: 'A' }) (a()) // true
isOfType ('A') (a()) // true
the-dr-lazy commented 5 years ago

@nikolay-borzov Are you interested to work on this?

nikolay-borzov commented 5 years ago

I can try. I am not good at TypeScript though

the-dr-lazy commented 5 years ago

@nikolay-borzov I assigned this issue to you.

I can try. I am not good at TypeScript though.

Let's try together; I'm 100% sure you can implement this feature. You can fork this repo from the master branch and work on it. If you encounter with any question/problem, I'm here and I hope I can help you.

kotarella1110 commented 4 years ago

Is there progress on this? I would like to implement this feature if there is no progress. May I create this PR?

the-dr-lazy commented 4 years ago

@kotarella1110 I think so. This issue was open for a long time.

the-dr-lazy commented 4 years ago

This feature will release in version 3.1.0. Thanks to @kotarella1110 and @nikolay-borzov.

the-dr-lazy commented 4 years ago

:tada: This issue has been resolved in version 3.1.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: