Skip to content

Commit 9fefc77

Browse files
fix(signals): allow generic template literals as state keys (#4871)
Closes #4638
1 parent 0ae7e3f commit 9fefc77

File tree

7 files changed

+62
-13
lines changed

7 files changed

+62
-13
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { expecter } from 'ts-snippet';
2+
import { compilerOptions } from './helpers';
3+
4+
describe('withEntities', () => {
5+
const expectSnippet = expecter(
6+
(code) => `
7+
import {
8+
patchState,
9+
signalStoreFeature,
10+
type,
11+
withMethods,
12+
} from '@ngrx/signals';
13+
import {
14+
addEntity,
15+
entityConfig,
16+
EntityId,
17+
withEntities,
18+
} from '@ngrx/signals/entities';
19+
20+
${code}
21+
`,
22+
compilerOptions()
23+
);
24+
25+
it('succeeds when creating a custom feature with named collection', () => {
26+
const snippet = `
27+
function withAddEntities<
28+
Entity extends { id: EntityId },
29+
Collection extends string
30+
>(
31+
collection: Collection
32+
) {
33+
const config = entityConfig({
34+
entity: type<Entity>(),
35+
collection,
36+
});
37+
38+
return signalStoreFeature(
39+
withEntities(config),
40+
withMethods((store) => ({
41+
addEntity(entity: Entity): void {
42+
patchState(store, addEntity(entity, { collection }));
43+
},
44+
}))
45+
);
46+
}
47+
`;
48+
49+
expectSnippet(snippet).toSucceed();
50+
});
51+
});

modules/signals/spec/types/patch-state.types.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ describe('patchState', () => {
3636

3737
it('fails with wrong partial state object', () => {
3838
expectSnippet('patchState(state, { x: 1 })').toFail(
39-
/'x' does not exist in type 'Partial<{ count: number; foo: string; }>/
39+
/'x' does not exist in type 'Partial<NoInfer<{ count: number; foo: string; }>>/
4040
);
4141
expectSnippet("patchState(state, { foo: 'baz' }, { x: 1 })").toFail(
42-
/'x' does not exist in type 'Partial<{ count: number; foo: string; }>/
42+
/'x' does not exist in type 'Partial<NoInfer<{ count: number; foo: string; }>>/
4343
);
4444
expectSnippet('patchState(state, { x: 1 }, { count: 0 })').toFail(
45-
/'x' does not exist in type 'Partial<{ count: number; foo: string; }>/
45+
/'x' does not exist in type 'Partial<NoInfer<{ count: number; foo: string; }>>/
4646
);
4747
expectSnippet('patchState(state, increment(), { x: 1 })').toFail(
48-
/'x' does not exist in type 'Partial<{ count: number; foo: string; }>/
48+
/'x' does not exist in type 'Partial<NoInfer<{ count: number; foo: string; }>>/
4949
);
5050
expectSnippet('patchState(state, { x: 1 }, increment())').toFail(
51-
/'x' does not exist in type 'Partial<{ count: number; foo: string; }>/
51+
/'x' does not exist in type 'Partial<NoInfer<{ count: number; foo: string; }>>/
5252
);
5353
});
5454

modules/signals/src/state-source.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
untracked,
99
WritableSignal,
1010
} from '@angular/core';
11-
import { Prettify } from './ts-helpers';
1211

1312
declare const ngDevMode: unknown;
1413

@@ -64,8 +63,7 @@ export function isWritableStateSource<State extends object>(
6463
export function patchState<State extends object>(
6564
stateSource: WritableStateSource<State>,
6665
...updaters: Array<
67-
| Partial<Prettify<NoInfer<State>>>
68-
| PartialStateUpdater<Prettify<NoInfer<State>>>
66+
Partial<NoInfer<State>> | PartialStateUpdater<NoInfer<State>>
6967
>
7068
): void {
7169
const currentState = untracked(() => getState(stateSource));

modules/signals/src/with-feature.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function withFeature<
3737
StateSignals<Input['state']> &
3838
Input['props'] &
3939
Input['methods'] &
40-
WritableStateSource<Prettify<Input['state']>>
40+
WritableStateSource<Input['state']>
4141
>
4242
) => SignalStoreFeature<Input, Output>
4343
): SignalStoreFeature<Input, Output> {

modules/signals/src/with-hooks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type HookFn<Input extends SignalStoreFeatureResult> = (
1212
StateSignals<Input['state']> &
1313
Input['props'] &
1414
Input['methods'] &
15-
WritableStateSource<Prettify<Input['state']>>
15+
WritableStateSource<Input['state']>
1616
>
1717
) => void;
1818

@@ -21,7 +21,7 @@ type HooksFactory<Input extends SignalStoreFeatureResult> = (
2121
StateSignals<Input['state']> &
2222
Input['props'] &
2323
Input['methods'] &
24-
WritableStateSource<Prettify<Input['state']>>
24+
WritableStateSource<Input['state']>
2525
>
2626
) => {
2727
onInit?: () => void;

modules/signals/src/with-methods.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function withMethods<
1919
StateSignals<Input['state']> &
2020
Input['props'] &
2121
Input['methods'] &
22-
WritableStateSource<Prettify<Input['state']>>
22+
WritableStateSource<Input['state']>
2323
>
2424
) => Methods
2525
): SignalStoreFeature<Input, { state: {}; props: {}; methods: Methods }> {

modules/signals/src/with-props.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function withProps<
1717
StateSignals<Input['state']> &
1818
Input['props'] &
1919
Input['methods'] &
20-
WritableStateSource<Prettify<Input['state']>>
20+
WritableStateSource<Input['state']>
2121
>
2222
) => Props
2323
): SignalStoreFeature<Input, { state: {}; props: Props; methods: {} }> {

0 commit comments

Comments
 (0)