signal-use-as-signal
This plugin check to valid signal use as signal.
- ⭐️ This rule is included in Flat Config
rdlabo.configs.recommended.- ✒️ The
--fixoption on the command line can automatically fix some of the problems reported by this rule.
Angular Signals are getter functions. Reading them requires (), and writing them must go through .set() or .update(). This rule catches code that uses a Signal variable as if it were a plain value, and it can auto-fix many common mistakes.
Rule Details
The rule tracks class properties initialized with Signal factories (signal, model, input, linkedSignal, toSignal, asReadonly) and reports misuse such as:
this.countinstead ofthis.count()in an expression contextthis.count() = valueinstead ofthis.count.set(value)this.user().name = 'Jane'instead ofthis.user.update(user => ({ ...user, name: 'Jane' }))this.items().push(x)instead ofthis.items.update(items => { items.push(x); return items; })this.#user = value(direct assignment to a Signal property) instead ofthis.#user.set(value)
The rule distinguishes between contexts where a Signal reference is expected and contexts where its value is expected. For example, passing a Signal object as a prop is allowed:
const props = { food: this.food };
launchModal({ food: this.food });
Examples
Incorrect
export class SigninPage {
readonly #id = signal<number | undefined>(undefined);
constructor() {
this.#id = 1;
}
useMethod() {
if (this.#id) {
this.#id().hoge = 1;
}
}
}
export class SigninPage {
readonly #user = signal<{ name: string }>({ name: 'John' });
updateUser() {
this.#user().name = 'Jane';
}
}
export class SigninPage {
readonly #numbers = signal<number[]>([1, 2, 3]);
updateNumbers() {
this.#numbers().push(4);
}
}
export class SigninPage {
readonly #value = signal<number>(0);
updateValue() {
this.#value() = 42;
}
}
Correct
export class SigninPage {
readonly #user = signal<{ name: string }>({ name: 'John' });
updateUser() {
this.#user.update((user) => ({ ...user, name: 'Jane' }));
}
}
export class SigninPage {
readonly #numbers = signal<number[]>([1, 2, 3]);
updateNumbers() {
this.#numbers.update((numbers) => {
numbers.push(4);
return numbers;
});
}
}
export class SigninPage {
readonly #value = signal<number>(0);
updateValue() {
this.#value.set(42);
}
}
export class SigninPage {
readonly food = signal<number>(0);
openPreview() {
const props = { food: this.food };
launchModal({ food: this.food });
}
}
Auto-fix
The rule provides auto-fix for the patterns above:
this.count = value->this.count.set(value)this.count() = value->this.count.set(value)this.count().x = value->this.count.update(value => ({ ...value, x: value }))this.count().push(x)->this.count.update(value => { value.push(x); return value; })
Options
This rule has no options.
When to enable
Enable this rule in any Angular project that uses Signals. It is complementary to @rdlabo/rules/signal-use-as-signal-template, which checks Signal usage in templates.