s-libs icon indicating copy to clipboard operation
s-libs copied to clipboard

[app-state] Make typing support selecting from optional objects

Open eric-simonton-sama opened this issue 3 years ago • 4 comments

E.g.

interface State {
  currentUser?: {
    name: string
  };
}

store('currentUser')('name');

Currently that causes a typescript error saying something like "never does not have a property 'name'". Instead make it work, and have the return type be Store<string | undefined>.

eric-simonton-sama avatar Nov 28 '22 20:11 eric-simonton-sama

This is straightforward when thinking about .$ or .state(). But how should it handle .set() and other mutating functions? If an ancestor could be undefined, those functions will fail.

Typescript does not allow: store.currentUser?.name = 'John', so it seems reasonable for AppState not to allow store('currentUser')('name').set('John')

So the question is: in what way should it be forbidden? So far the answer has been to force the user to declare the store to be defined:

store<'currentUser', User>('currentUser')('name').set('John'); // require this
store.currentUser!.name = 'John'; // analogous to this

Another option could be to carry some kind of flag in the typing of Store object to indicate whether they are writable. Maybe a read-only store interface that is returned when a parent store could be undefined.

ersimont avatar Dec 05 '22 02:12 ersimont

Potential typing for the read-only part of things:

type GetSlice<T> = <K extends keyof NonNullable<T>>(
  attr: K,
) => Store<NonNullable<T>[K] | IfCouldBe<Nil, T, undefined>>;

export interface Store<T> extends GetSlice<T> {
  /**
   * Select a slice of the store to operate on. For example `store('currentUser')` will return a new `Store` that represents the `currentUser` property.
   */
  <K extends keyof NonNullable<T>>(attr: K): Store<
    NonNullable<T>[K] | IfCouldBe<Nil, T, undefined>
  >;
}

ersimont avatar Dec 05 '22 02:12 ersimont

This would also be a good to add .delete() to signal-store, and have it only work for undefined-able things.

ersimont avatar Jan 02 '24 00:01 ersimont

This will be available in signal-store starting in v18.

ersimont avatar May 11 '24 23:05 ersimont