Skip to content

Commit 5d66296

Browse files
fix: extend check to other built-in object types
1 parent d4abbd8 commit 5d66296

File tree

5 files changed

+167
-128
lines changed

5 files changed

+167
-128
lines changed

modules/signals/spec/deep-signal.spec.ts

+60-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { toDeepSignal } from '../src/deep-signal';
21
import { isSignal, signal } from '@angular/core';
2+
import { toDeepSignal } from '../src/deep-signal';
33

44
describe('toDeepSignal', () => {
55
it('creates deep signals for plain objects', () => {
@@ -56,27 +56,53 @@ describe('toDeepSignal', () => {
5656
expect(deepBool).toBe(bool);
5757
});
5858

59-
it('does not create deep signals for built-in object types', () => {
59+
it('does not create deep signals for iterables', () => {
6060
const array = signal([]);
6161
const set = signal(new Set());
6262
const map = signal(new Map());
63-
const date = signal(new Date());
64-
const error = signal(new Error());
65-
const regExp = signal(new RegExp(''));
63+
const uintArray = signal(new Uint32Array());
64+
const floatArray = signal(new Float64Array());
6665

6766
const deepArray = toDeepSignal(array);
6867
const deepSet = toDeepSignal(set);
6968
const deepMap = toDeepSignal(map);
70-
const deepDate = toDeepSignal(date);
71-
const deepError = toDeepSignal(error);
72-
const deepRegExp = toDeepSignal(regExp);
69+
const deepUintArray = toDeepSignal(uintArray);
70+
const deepFloatArray = toDeepSignal(floatArray);
7371

7472
expect(deepArray).toBe(array);
7573
expect(deepSet).toBe(set);
7674
expect(deepMap).toBe(map);
75+
expect(deepUintArray).toBe(uintArray);
76+
expect(deepFloatArray).toBe(floatArray);
77+
});
78+
79+
it('does not create deep signals for built-in object types', () => {
80+
const weakSet = signal(new WeakSet());
81+
const weakMap = signal(new WeakMap());
82+
const promise = signal(Promise.resolve(10));
83+
const date = signal(new Date());
84+
const error = signal(new Error());
85+
const regExp = signal(new RegExp(''));
86+
const arrayBuffer = signal(new ArrayBuffer(10));
87+
const dataView = signal(new DataView(new ArrayBuffer(10)));
88+
89+
const deepWeakSet = toDeepSignal(weakSet);
90+
const deepWeakMap = toDeepSignal(weakMap);
91+
const deepPromise = toDeepSignal(promise);
92+
const deepDate = toDeepSignal(date);
93+
const deepError = toDeepSignal(error);
94+
const deepRegExp = toDeepSignal(regExp);
95+
const deepArrayBuffer = toDeepSignal(arrayBuffer);
96+
const deepDataView = toDeepSignal(dataView);
97+
98+
expect(deepWeakSet).toBe(weakSet);
99+
expect(deepWeakMap).toBe(weakMap);
100+
expect(deepPromise).toBe(promise);
77101
expect(deepDate).toBe(date);
78102
expect(deepError).toBe(error);
79103
expect(deepRegExp).toBe(regExp);
104+
expect(deepArrayBuffer).toBe(arrayBuffer);
105+
expect(deepDataView).toBe(dataView);
80106
});
81107

82108
it('does not create deep signals for functions', () => {
@@ -93,21 +119,43 @@ describe('toDeepSignal', () => {
93119
expect(deepFn3).toBe(fn3);
94120
});
95121

96-
it('does not create deep signals for custom class instances that extend built-in object types', () => {
122+
it('does not create deep signals for custom class instances that are iterables', () => {
97123
class CustomArray extends Array {}
124+
98125
class CustomSet extends Set {}
99-
class CustomError extends Error {}
126+
127+
class CustomFloatArray extends Float32Array {}
100128

101129
const array = signal(new CustomArray());
130+
const floatArray = signal(new CustomFloatArray());
102131
const set = signal(new CustomSet());
103-
const error = signal(new CustomError());
104132

105133
const deepArray = toDeepSignal(array);
134+
const deepFloatArray = toDeepSignal(floatArray);
106135
const deepSet = toDeepSignal(set);
107-
const deepError = toDeepSignal(error);
108136

109137
expect(deepArray).toBe(array);
138+
expect(deepFloatArray).toBe(floatArray);
110139
expect(deepSet).toBe(set);
140+
});
141+
142+
it('does not create deep signals for custom class instances that extend built-in object types', () => {
143+
class CustomWeakMap extends WeakMap {}
144+
145+
class CustomError extends Error {}
146+
147+
class CustomArrayBuffer extends ArrayBuffer {}
148+
149+
const weakMap = signal(new CustomWeakMap());
150+
const error = signal(new CustomError());
151+
const arrayBuffer = signal(new CustomArrayBuffer(10));
152+
153+
const deepWeakMap = toDeepSignal(weakMap);
154+
const deepError = toDeepSignal(error);
155+
const deepArrayBuffer = toDeepSignal(arrayBuffer);
156+
157+
expect(deepWeakMap).toBe(weakMap);
111158
expect(deepError).toBe(error);
159+
expect(deepArrayBuffer).toBe(arrayBuffer);
112160
});
113161
});

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

+41-49
Original file line numberDiff line numberDiff line change
@@ -118,91 +118,83 @@ describe('signalState', () => {
118118
expectSnippet(snippet).toInfer('set', 'Signal<Set<{ foo: number; }>>');
119119
});
120120

121-
it('does not create deep signals for an array', () => {
121+
it('does not create deep signals for iterables', () => {
122122
const snippet = `
123-
const state = signalState<string[]>([]);
124-
declare const stateKeys: keyof typeof state;
123+
const arrayState = signalState<string[]>([]);
124+
declare const arrayStateKeys: keyof typeof arrayState;
125+
126+
const setState = signalState(new Set<number>());
127+
declare const setStateKeys: keyof typeof setState;
128+
129+
const mapState = signalState(new Map<number, { bar: boolean }>());
130+
declare const mapStateKeys: keyof typeof mapState;
131+
132+
const uintArrayState = signalState(new Uint8ClampedArray());
133+
declare const uintArrayStateKeys: keyof typeof uintArrayState;
125134
`;
126135

127136
expectSnippet(snippet).toSucceed();
128137

129138
expectSnippet(snippet).toInfer(
130-
'stateKeys',
139+
'arrayStateKeys',
131140
'unique symbol | keyof Signal<string[]>'
132141
);
133-
});
134-
135-
it('does not create deep signals for Set', () => {
136-
const snippet = `
137-
const state = signalState(new Set<number>());
138-
declare const stateKeys: keyof typeof state;
139-
`;
140-
141-
expectSnippet(snippet).toSucceed();
142142

143143
expectSnippet(snippet).toInfer(
144-
'stateKeys',
144+
'setStateKeys',
145145
'unique symbol | keyof Signal<Set<number>>'
146146
);
147-
});
148-
149-
it('does not create deep signals for Map', () => {
150-
const snippet = `
151-
const state = signalState(new Map<number, { bar: boolean }>());
152-
declare const stateKeys: keyof typeof state;
153-
`;
154-
155-
expectSnippet(snippet).toSucceed();
156147

157148
expectSnippet(snippet).toInfer(
158-
'stateKeys',
149+
'mapStateKeys',
159150
'unique symbol | keyof Signal<Map<number, { bar: boolean; }>>'
160151
);
161-
});
162-
163-
it('does not create deep signals for Date', () => {
164-
const snippet = `
165-
const state = signalState(new Date());
166-
declare const stateKeys: keyof typeof state;
167-
`;
168-
169-
expectSnippet(snippet).toSucceed();
170152

171153
expectSnippet(snippet).toInfer(
172-
'stateKeys',
173-
'unique symbol | keyof Signal<Date>'
154+
'uintArrayStateKeys',
155+
'unique symbol | keyof Signal<Uint8ClampedArray>'
174156
);
175157
});
176158

177-
it('does not create deep signals for Error', () => {
159+
it('does not create deep signals for built-in object types', () => {
178160
const snippet = `
179-
const state = signalState(new Error());
180-
declare const stateKeys: keyof typeof state;
161+
const weakSetState = signalState(new WeakSet<{ foo: string }>());
162+
declare const weakSetStateKeys: keyof typeof weakSetState;
163+
164+
const dateState = signalState(new Date());
165+
declare const dateStateKeys: keyof typeof dateState;
166+
167+
const errorState = signalState(new Error());
168+
declare const errorStateKeys: keyof typeof errorState;
169+
170+
const regExpState = signalState(new RegExp(''));
171+
declare const regExpStateKeys: keyof typeof regExpState;
181172
`;
182173

183174
expectSnippet(snippet).toSucceed();
184175

185176
expectSnippet(snippet).toInfer(
186-
'stateKeys',
187-
'unique symbol | keyof Signal<Error>'
177+
'weakSetStateKeys',
178+
'unique symbol | keyof Signal<WeakSet<{ foo: string; }>>'
188179
);
189-
});
190180

191-
it('does not create deep signals for RegExp', () => {
192-
const snippet = `
193-
const state = signalState(new RegExp(''));
194-
declare const stateKeys: keyof typeof state;
195-
`;
181+
expectSnippet(snippet).toInfer(
182+
'dateStateKeys',
183+
'unique symbol | keyof Signal<Date>'
184+
);
196185

197-
expectSnippet(snippet).toSucceed();
186+
expectSnippet(snippet).toInfer(
187+
'errorStateKeys',
188+
'unique symbol | keyof Signal<Error>'
189+
);
198190

199191
expectSnippet(snippet).toInfer(
200-
'stateKeys',
192+
'regExpStateKeys',
201193
'unique symbol | keyof Signal<RegExp>'
202194
);
203195
});
204196

205-
it('does not create deep signals for Function', () => {
197+
it('does not create deep signals for functions', () => {
206198
const snippet = `
207199
const state = signalState(() => {});
208200
declare const stateKeys: keyof typeof state;

modules/signals/spec/types/signal-store.types.spec.ts

+35-53
Original file line numberDiff line numberDiff line change
@@ -163,79 +163,61 @@ describe('signalStore', () => {
163163
expectSnippet(snippet).toInfer('set', 'Signal<Set<number>>');
164164
});
165165

166-
it('does not create deep signals when state type is an array', () => {
166+
it('does not create deep signals when state type is an iterable', () => {
167167
const snippet = `
168-
const Store = signalStore(withState<number[]>([]));
169-
const store = new Store();
170-
declare const storeKeys: keyof typeof store;
171-
`;
172-
173-
expectSnippet(snippet).toSucceed();
174-
175-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
176-
});
177-
178-
it('does not create deep signals when state type is Set', () => {
179-
const snippet = `
180-
const Store = signalStore(withState(new Set<{ foo: string }>()));
181-
const store = new Store();
182-
declare const storeKeys: keyof typeof store;
183-
`;
184-
185-
expectSnippet(snippet).toSucceed();
186-
187-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
188-
});
189-
190-
it('does not create deep signals when state type is Map', () => {
191-
const snippet = `
192-
const Store = signalStore(withState(new Map<string, { foo: number }>()));
193-
const store = new Store();
194-
declare const storeKeys: keyof typeof store;
195-
`;
168+
const ArrayStore = signalStore(withState<number[]>([]));
169+
const arrayStore = new ArrayStore();
170+
declare const arrayStoreKeys: keyof typeof arrayStore;
196171
197-
expectSnippet(snippet).toSucceed();
172+
const SetStore = signalStore(withState(new Set<{ foo: string }>()));
173+
const setStore = new SetStore();
174+
declare const setStoreKeys: keyof typeof setStore;
198175
199-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
200-
});
176+
const MapStore = signalStore(withState(new Map<string, { foo: number }>()));
177+
const mapStore = new MapStore();
178+
declare const mapStoreKeys: keyof typeof mapStore;
201179
202-
it('does not create deep signals when state type is Date', () => {
203-
const snippet = `
204-
const Store = signalStore(withState(new Date()));
205-
const store = new Store();
206-
declare const storeKeys: keyof typeof store;
180+
const FloatArrayStore = signalStore(withState(new Float32Array()));
181+
const floatArrayStore = new FloatArrayStore();
182+
declare const floatArrayStoreKeys: keyof typeof floatArrayStore;
207183
`;
208184

209185
expectSnippet(snippet).toSucceed();
210186

211-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
187+
expectSnippet(snippet).toInfer('arrayStoreKeys', 'unique symbol');
188+
expectSnippet(snippet).toInfer('setStoreKeys', 'unique symbol');
189+
expectSnippet(snippet).toInfer('mapStoreKeys', 'unique symbol');
190+
expectSnippet(snippet).toInfer('floatArrayStoreKeys', 'unique symbol');
212191
});
213192

214-
it('does not create deep signals when state type is Error', () => {
193+
it('does not create deep signals when state type is a built-in object type', () => {
215194
const snippet = `
216-
const Store = signalStore(withState(new Error()));
217-
const store = new Store();
218-
declare const storeKeys: keyof typeof store;
219-
`;
195+
const WeakMapStore = signalStore(withState(new WeakMap<{ foo: string }, { bar: number }>()));
196+
const weakMapStore = new WeakMapStore();
197+
declare const weakMapStoreKeys: keyof typeof weakMapStore;
220198
221-
expectSnippet(snippet).toSucceed();
199+
const DateStore = signalStore(withState(new Date()));
200+
const dateStore = new DateStore();
201+
declare const dateStoreKeys: keyof typeof dateStore;
222202
223-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
224-
});
203+
const ErrorStore = signalStore(withState(new Error()));
204+
const errorStore = new ErrorStore();
205+
declare const errorStoreKeys: keyof typeof errorStore;
225206
226-
it('does not create deep signals when state type is RegExp', () => {
227-
const snippet = `
228-
const Store = signalStore(withState(new RegExp('')));
229-
const store = new Store();
230-
declare const storeKeys: keyof typeof store;
207+
const RegExpStore = signalStore(withState(new RegExp('')));
208+
const regExpStore = new RegExpStore();
209+
declare const regExpStoreKeys: keyof typeof regExpStore;
231210
`;
232211

233212
expectSnippet(snippet).toSucceed();
234213

235-
expectSnippet(snippet).toInfer('storeKeys', 'unique symbol');
214+
expectSnippet(snippet).toInfer('weakMapStoreKeys', 'unique symbol');
215+
expectSnippet(snippet).toInfer('dateStoreKeys', 'unique symbol');
216+
expectSnippet(snippet).toInfer('errorStoreKeys', 'unique symbol');
217+
expectSnippet(snippet).toInfer('regExpStoreKeys', 'unique symbol');
236218
});
237219

238-
it('does not create deep signals when state type is Function', () => {
220+
it('does not create deep signals when state type is a function', () => {
239221
const snippet = `
240222
const Store = signalStore(withState(() => () => {}));
241223
const store = new Store();

0 commit comments

Comments
 (0)