From bcca4a6fa2faa5b42d77c9f2f2ab4cf2e06e0d15 Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Mon, 9 Mar 2026 19:14:38 +0100 Subject: [PATCH] refactor(core): expose `previousValue` as undefined This change introduces a union type of distinguish cases where `previousValue` can be undefined. --- goldens/public-api/core/index.api.md | 20 ++++++++----- .../src/change_detection/simple_change.ts | 30 ++++++++++++++----- .../render3/features/ng_onchanges_feature.ts | 2 +- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/goldens/public-api/core/index.api.md b/goldens/public-api/core/index.api.md index 9bffb3f16bd6..bc1337237ff2 100644 --- a/goldens/public-api/core/index.api.md +++ b/goldens/public-api/core/index.api.md @@ -1799,16 +1799,20 @@ export type Signal = (() => T) & { export function signal(initialValue: T, options?: CreateSignalOptions): WritableSignal; // @public -export class SimpleChange { - constructor(previousValue: T, currentValue: T, firstChange: boolean); - // (undocumented) +export type SimpleChange = { + previousValue: T; currentValue: T; - // (undocumented) - firstChange: boolean; + firstChange: false; + isFirstChange(): false; +} | { + previousValue: T | undefined; + currentValue: T; + firstChange: true; isFirstChange(): boolean; - // (undocumented) - previousValue: T; -} +}; + +// @public (undocumented) +export const SimpleChange: ɵSimpleChangeCtor; // @public export type SimpleChanges = T extends object ? { diff --git a/packages/core/src/change_detection/simple_change.ts b/packages/core/src/change_detection/simple_change.ts index a826d455391d..04c3640082e7 100644 --- a/packages/core/src/change_detection/simple_change.ts +++ b/packages/core/src/change_detection/simple_change.ts @@ -17,19 +17,35 @@ import type {ɵINPUT_SIGNAL_BRAND_READ_TYPE} from '../authoring/input/input_sign * * @publicApi */ -export class SimpleChange { +export type SimpleChange = + | { + previousValue: T; + currentValue: T; + firstChange: false; + isFirstChange(): false; + } + | { + previousValue: T | undefined; + currentValue: T; + firstChange: true; + isFirstChange(): boolean; + }; + +export interface ɵSimpleChangeCtor { + new (previousValue: unknown, currentValue: unknown, firstChange: boolean): SimpleChange; +} + +export const SimpleChange: ɵSimpleChangeCtor = class SimpleChange { constructor( - public previousValue: T, - public currentValue: T, + public previousValue: unknown, + public currentValue: unknown, public firstChange: boolean, ) {} - /** - * Check whether the new value is the first value assigned. - */ + isFirstChange(): boolean { return this.firstChange; } -} +} as ɵSimpleChangeCtor; /** * A hashtable of changes represented by {@link SimpleChange} objects stored diff --git a/packages/core/src/render3/features/ng_onchanges_feature.ts b/packages/core/src/render3/features/ng_onchanges_feature.ts index 600bacd998fe..72ce923969e0 100644 --- a/packages/core/src/render3/features/ng_onchanges_feature.ts +++ b/packages/core/src/render3/features/ng_onchanges_feature.ts @@ -8,11 +8,11 @@ import {InputSignalNode} from '../../authoring/input/input_signal_node'; import {OnChanges} from '../../change_detection/lifecycle_hooks'; +import {SimpleChange, SimpleChanges} from '../../change_detection/simple_change'; import {assertString} from '../../util/assert'; import {EMPTY_OBJ} from '../../util/empty'; import {applyValueToInputField} from '../apply_value_input_field'; import {DirectiveDef, DirectiveDefFeature} from '../interfaces/definition'; -import {SimpleChange, SimpleChanges} from '../../change_detection/simple_change'; /** * The NgOnChangesFeature decorates a component with support for the ngOnChanges