cartant/ts-action

Request: Documentation update with Typescript class/interface example

Closed this issue · 10 comments

Hi,
I am requesting that you please update your docs or specs with an example that demonstrates how to use ts-action with typescript class and interface instead plain Javascript objects as found in the examples.

Cheers

I don't understand what it is you are asking. I can only guess that you want to store a class in your state. You should not do that, as the state should be serializable to a deserializable from JSON.

If that is what you are looking to do, it's not something I will be documenting, as it's not a practice that I would encourage. And, in any case, doing so would have nothing to do with ts-action which is only concerned with declaring and narrowing actions - and not with what's done inside reducers.

Thanks for your quick reply.
Using typescript-fsa I can do the following that works:

import actionCreatorFactory from 'typescript-fsa'
import { reducerWithInitialState } from 'typescript-fsa-reducers'
import {
  FormState, IFormState
} from '../../../shared/shared.store/store.util'

 interface ILanguage {
  first: string
  second: string
}

class Language {
  first: string = ''
  second: string = ''
}

const languageDataAcf = actionCreatorFactory( '[Language]' )

export const addLanguageDataAction = languageDataAcf<ILanguage>( 'ADD_DATA' )

function addLanguageDataHandler( state: ILanguage, language: ILanguage ): ILanguage {
  return Object.assign( {}, state, language )
}

export const updateLanguageDataAction = languageDataAcf<ILanguage>( 'UPDATE_DATA' )

function updateLanguageDataHandler( state: ILanguage, language: ILanguage ): ILanguage {
  return Object.assign( {}, state, language )
}

export const initLanguageDataAction = languageDataAcf<ILanguage>( 'INIT_DATA' )

function initLanguageDataHandler( state: ILanguage ): ILanguage {
  return Object.assign( {}, state, new Language() )
}

export const languageDataReducer = reducerWithInitialState( new Language() )
    .case( addLanguageDataAction, addLanguageDataHandler )
    .case( initLanguageDataAction, initLanguageDataHandler )
    .case( updateLanguageDataAction, updateLanguageDataHandler )

I am looking for someway to do the same with ts-action. Hence the documentation request.

Is this possible with ts-action?

Cheers

There is an example in the README that can be extrapolated into what it seems you want to do:

import { action, on, payload, reducer } from "ts-action";

const Foo = action("FOO", payload<{ foo: number }>());
const Bar = action("BAR", payload<{ bar: number }>());

interface State { foo?: number; bar?: number; }
const initialState = {};

const fooBarReducer = reducer<State>([
  on(Foo, (state, { payload }) => ({ ...state, foo: payload.foo })),
  on(Bar, (state, { payload }) => ({ ...state, bar: payload.bar }))
], initialState);

I've updated the README to use an interface for the state - rather than a type alias - and to make explicit what the initial state is.

As far as I can see, the only difference between this and what you are doing, is that you are creating classes and are adding them to the state. And that's not something that I would encourage.

Thanks. I will try your suggestion now. You do close an issue rather fast though.

Hi,
I copied and paste the following from https://github.com/cartant/ts-action#props

import { action, on, payload, reducer } from "ts-action";

const Foo = action("FOO", payload<{ foo: number }>());
const Bar = action("BAR", payload<{ bar: number }>());

interface State { foo?: number; bar?: number; }
const initialState = {};

const fooBarReducer = reducer<State>([
  on(Foo, (state, { payload }) => ({ ...state, foo: payload.foo })),
  on(Bar, (state, { payload }) => ({ ...state, bar: payload.bar }))
], initialState);

Surprisingly, the payload in the function call (state, { payload } in the fooBarReducer is not resolved (error). The error states that | Type "Readonly type: 'Foo'}" has no property payload and no string index signature.

Should this be so?

Cheers

For me, pasted into a project, that code is compiled by TypeScript without error - using TypeScript 2.6.1.

I was using "typescript": "^2.5.3". After updating to 2.6.1 the error disappear! I think this might be the reason for all my previous questions. I will start all over again and see if I can get ts-action to work in my project.

Thanks

Good to hear that it's now working for you. I'm a little surprised that there are problems with 2.5.3, as the critical features that ts-action depends upon were introduced in TypeScript 2.1.

I did some experimenting with earlier versions of TypeScript as I was building the package and, at one stage, it was working with 2.1. If there are problems with 2.5.3, the problems likely relate to more recent changes made to ts-action.

I will look into this and will update the README once I've established what the problem and minimum TypeScript version are. Thanks.

Yeah. 2.6 is required, as the inferences that are required to be made in union and in on fail with 2.5.

Rather than qualify what does and does not work, I've updated the README to specify 2.6 as the minimum version. Thanks for bringing this to my attention.

Great!! I was beginning to doubt myself! All end well at the moment. No problems whatsoever since upgrading.

I am now looking into how I can use ts-action-operators. Don't be surprise if you see some queries there from me.

Cheers