Skip to content

@frp-ts/state addition #53

@PalmZE

Description

@PalmZE

@raveclassic, hi!

Would you accept the below feature as a separate frp-ts package\addition to the core package?

// API

type StateActions<S> = Record<string, (this: S, ...args: any[]) => undefined | void>;

type OmitThis<AS extends StateActions<any>> = {
  [K in keyof AS]: AS[K] extends (this: any, ...args: infer U) => void | undefined ? (...args: U) => void : never;
};

export const newState = <S, AS extends StateActions<S>>(initial: S, actions: AS): Property<S> & OmitThis<AS> => {
  throw Error('impl is skipped');
};

// USAGE

interface Dog {
  name: string;
}
interface House {
  dog: Dog;
}
interface AppState {
  house: House;
}

const initialState: AppState = { house: { dog: { name: 'Fido' } } };

const store = newState(initialState, {
  renameTheDog(newName: string) {
    // this is typed correctly : AppState
    this.house.dog.name = newName;
  },
});

// typed correctly, this is omitted
store.renameTheDog('Odif');

Internally it will use immer to support concise mutation syntax.

Motivation

I find it convenient to group store\vm state into a single object and expose a single atom in the API. This leads to some boilerplate when you need to modify parts of the state.
Immer helps a lot, but we still need to use modify calls. This change simplifies this use case.

Besides, some libraries provide this out of the box (SolidJS as example).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions