ngxtension / ngxtension-platform

Utilities for Angular

Home Page:https://ngxtension.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

signalSlice: action stream inferred as never

dirkluijk opened this issue · comments

Considering this snippet:

interface MyState {
  foo: string;
}

const mySlice = signalSlice({
  initialState: {
    foo: 'bar'
  } as MyState,
  actionSources: {
    update: (state: Signal<MyState>, newFoo: string): Observable<MyState> =>
      of({ foo: newFoo })
  }
});

When I want to use mySlice.update$ it is inferred as never.

I checked the source code, and I have the idea that there is a small mistake in this definition:

type ActionStreams<
	TSignalValue,
	TActionSources extends NamedActionSources<TSignalValue>,
> = {
	[K in keyof TActionSources &
		string as `${K}$`]: TActionSources[K] extends Reducer<TSignalValue, unknown>
		? Observable<void>
		: TActionSources[K] extends Reducer<TSignalValue, infer TValue>
			? TValue extends Observable<any>
				? TValue
				: Observable<TValue>
			: never;
};

I think it might need to be:

type ActionStreams<
	TSignalValue,
	TActionSources extends NamedActionSources<TSignalValue>,
> = {
	[K in keyof TActionSources &
		string as `${K}$`]: TActionSources[K] extends ActionSourceFn<TSignalValue, unknown>
		? Observable<void>
		: TActionSources[K] extends ActionSourceFn<TSignalValue, infer TValue>
			? TValue extends Observable<any>
				? TValue
				: Observable<TValue>
			: never;
};

If this is correct, I could arrange an MR. Just checking if I am maybe doing something wrong?

You are probably correct, feel free to open a PR and I can review more closely - would you also be able to add a test or two to cover this and test that this values received from the action stream are what is expected?

Also, and this doesn't change the fact that action streams should work, but I wonder if the experimental Action Effects API would fill the role of what you are trying to do with action streams: #296

e.g. you might do something like:

const mySlice = signalSlice({
  initialState: {
    foo: 'bar'
  } as MyState,
  actionSources: {
    update: (state: Signal<MyState>, newFoo: string): Observable<MyState> =>
      of({ foo: newFoo })
  },
  actionEffects: () => ({
    update: (action) => {
      // side effect in response to update actionSource emitting
    }
  })
});

Hello, this seems to still be an issue in v4.0.0, should I open a PR with @dirkluijk proposal ?

@Pilpin yes feel free to open a PR

I'm actually not sure what to test for as the issue is in the type of the variable in the IDE, not during runtime.
But AFAIK @dirkluijk fix does pass the tests already present.
PR => #472