Skip to content

Commit 76adbbc

Browse files
JeanMecheatscott
authored andcommitted
refactor(core): expose isWritableSignal to the publicApi
This is alongside the already exisiting isSignal() fixes #64763
1 parent 662f0e5 commit 76adbbc

File tree

6 files changed

+46
-19
lines changed

6 files changed

+46
-19
lines changed

goldens/public-api/core/index.api.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,9 @@ export function isSignal(value: unknown): value is Signal<unknown>;
10451045
// @public
10461046
export function isStandalone(type: Type<unknown>): boolean;
10471047

1048+
// @public
1049+
export function isWritableSignal(value: unknown): value is WritableSignal<unknown>;
1050+
10481051
// @public
10491052
export interface IterableChangeRecord<V> {
10501053
readonly currentIndex: number | null;

packages/core/src/core_reactivity_export_internal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
export {SIGNAL as ɵSIGNAL} from '../primitives/signals';
1010

11-
export {isSignal, Signal, ValueEqualityFn} from './render3/reactivity/api';
11+
export {isSignal, isWritableSignal, Signal, ValueEqualityFn} from './render3/reactivity/api';
1212
export {computed, CreateComputedOptions} from './render3/reactivity/computed';
1313
export {
1414
CreateSignalOptions,

packages/core/src/render3/instructions/two_way.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import type {EventCallback} from '../../event_delegation_utils';
1010
import {bindingUpdated} from '../bindings';
1111
import {SanitizerFn} from '../interfaces/sanitization';
1212
import {RENDERER} from '../interfaces/view';
13-
import {isWritableSignal, WritableSignal} from '../reactivity/signal';
13+
import {isWritableSignal} from '../reactivity/api';
14+
import {WritableSignal} from '../reactivity/signal';
1415
import {getCurrentTNode, getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';
1516

1617
import {listenerInternal} from './listener';

packages/core/src/render3/reactivity/api.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import {SIGNAL} from '../../../primitives/signals';
10+
import type {WritableSignal} from './signal';
1011

1112
/**
1213
* A reactive value which notifies consumers of any changes.
@@ -37,3 +38,12 @@ export function isSignal(value: unknown): value is Signal<unknown> {
3738
* @publicApi 17.0
3839
*/
3940
export type ValueEqualityFn<T> = (a: T, b: T) => boolean;
41+
42+
/**
43+
* Checks if the given `value` is a writeable signal.
44+
*
45+
* @publicApi 21.1
46+
*/
47+
export function isWritableSignal(value: unknown): value is WritableSignal<unknown> {
48+
return isSignal(value) && typeof (value as any).set === 'function';
49+
}

packages/core/src/render3/reactivity/signal.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,9 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {
10-
createSignal,
11-
SIGNAL,
12-
SignalGetter,
13-
SignalNode,
14-
signalSetFn,
15-
signalUpdateFn,
16-
} from '../../../primitives/signals';
9+
import {createSignal, SIGNAL, SignalGetter, SignalNode} from '../../../primitives/signals';
1710

18-
import {isSignal, Signal, ValueEqualityFn} from './api';
11+
import {Signal, ValueEqualityFn} from './api';
1912

2013
/** Symbol used distinguish `WritableSignal` from other non-writable signals and functions. */
2114
export const ɵWRITABLE_SIGNAL: unique symbol = /* @__PURE__ */ Symbol('WRITABLE_SIGNAL');
@@ -102,10 +95,3 @@ export function signalAsReadonlyFn<T>(this: SignalGetter<T>): Signal<T> {
10295
}
10396
return node.readonlyFn;
10497
}
105-
106-
/**
107-
* Checks if the given `value` is a writeable signal.
108-
*/
109-
export function isWritableSignal(value: unknown): value is WritableSignal<unknown> {
110-
return isSignal(value) && typeof (value as any).set === 'function';
111-
}

packages/core/test/signals/is_signal_spec.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import {computed, isSignal, signal} from '../../src/core';
9+
import {computed, isSignal, isWritableSignal, signal} from '../../src/core';
1010

1111
describe('isSignal', () => {
1212
it('should return true for writable signal', () => {
@@ -34,3 +34,30 @@ describe('isSignal', () => {
3434
expect(isSignal(fn)).toBe(false);
3535
});
3636
});
37+
38+
describe('isWritableSignal', () => {
39+
it('should return true for writable signal', () => {
40+
const writableSignal = signal('Angular');
41+
expect(isWritableSignal(writableSignal)).toBe(true);
42+
});
43+
44+
it('should return false for readonly signal', () => {
45+
const readonlySignal = computed(() => 10);
46+
expect(isWritableSignal(readonlySignal)).toBe(false);
47+
});
48+
49+
it('should return false for primitive', () => {
50+
const primitive = 0;
51+
expect(isWritableSignal(primitive)).toBe(false);
52+
});
53+
54+
it('should return false for object', () => {
55+
const object = {name: 'Angular'};
56+
expect(isWritableSignal(object)).toBe(false);
57+
});
58+
59+
it('should return false for function', () => {
60+
const fn = () => {};
61+
expect(isWritableSignal(fn)).toBe(false);
62+
});
63+
});

0 commit comments

Comments
 (0)