Skip to content

Commit b78042f

Browse files
devversionthePunderWoman
authored andcommitted
refactor(core): separate InputSignal and InputSignalWithTransform (angular#54053)
This commit separates `InputSignal` for input signals with transforms. The reason being that most of the time, signal inputs are not using transforms and the generics are rather confusing. Especially for users with inferred types displayed in their IDEs, the input signal types are seemingly complex, even if no transform is used. For this reason, we are introducing a new type called `InputSignalWithTransform`. This type will be used for inputs with transforms, while non-transform inputs just use `InputSignal`. A notable fact is that `InputSignal` extends `InputSignalWithTransform`, with the "identity transform". i.e. there is no transform. This allows us to share the code for input signals. In practice, we don't expect users to pass around `InputSignal`'s anyway. PR Close angular#54053
1 parent d38238e commit b78042f

File tree

13 files changed

+147
-149
lines changed

13 files changed

+147
-149
lines changed

goldens/public-api/core/index.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -883,10 +883,10 @@ export interface InputFunction {
883883
// (undocumented)
884884
<ReadT>(initialValue: ReadT, opts?: InputOptionsWithoutTransform<ReadT>): InputSignal<ReadT>;
885885
// (undocumented)
886-
<ReadT, WriteT>(initialValue: ReadT, opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignal<ReadT, WriteT>;
886+
<ReadT, WriteT>(initialValue: ReadT, opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignalWithTransform<ReadT, WriteT>;
887887
required: {
888888
<ReadT>(opts?: InputOptionsWithoutTransform<ReadT>): InputSignal<ReadT>;
889-
<ReadT, WriteT>(opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignal<ReadT, WriteT>;
889+
<ReadT, WriteT>(opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignalWithTransform<ReadT, WriteT>;
890890
};
891891
}
892892

@@ -905,7 +905,11 @@ export type InputOptionsWithoutTransform<ReadT> = Omit<InputOptions<ReadT, ReadT
905905
export type InputOptionsWithTransform<ReadT, WriteT> = Required<Pick<InputOptions<ReadT, WriteT>, 'transform'>> & InputOptions<ReadT, WriteT>;
906906

907907
// @public
908-
export interface InputSignal<ReadT, WriteT = ReadT> extends Signal<ReadT> {
908+
export interface InputSignal<ReadT> extends InputSignalWithTransform<ReadT, ReadT> {
909+
}
910+
911+
// @public
912+
export interface InputSignalWithTransform<ReadT, WriteT> extends Signal<ReadT> {
909913
// (undocumented)
910914
INPUT_SIGNAL_BRAND_READ_TYPE]: ReadT;
911915
// (undocumented)

packages/compiler-cli/src/ngtsc/testing/fake_core/index.ts

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -141,41 +141,28 @@ export type InputOptionsWithTransform<ReadT, WriteT> =
141141
const ɵINPUT_SIGNAL_BRAND_READ_TYPE = /* @__PURE__ */ Symbol();
142142
export const ɵINPUT_SIGNAL_BRAND_WRITE_TYPE = /* @__PURE__ */ Symbol();
143143

144-
export interface InputSignal<ReadT, WriteT = ReadT> extends Signal<ReadT> {
144+
export interface InputSignalWithTransform<ReadT, WriteT> extends Signal<ReadT> {
145145
[ɵINPUT_SIGNAL_BRAND_READ_TYPE]: ReadT;
146146
[ɵINPUT_SIGNAL_BRAND_WRITE_TYPE]: WriteT;
147147
}
148+
export interface InputSignal<ReadT> extends InputSignalWithTransform<ReadT, ReadT> {}
148149

149-
export function inputFunction<ReadT>(): InputSignal<ReadT|undefined>;
150-
export function inputFunction<ReadT>(
151-
initialValue: ReadT, opts?: InputOptionsWithoutTransform<ReadT>): InputSignal<ReadT>;
152-
export function inputFunction<ReadT, WriteT>(
153-
initialValue: ReadT,
154-
opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignal<ReadT, WriteT>;
155-
export function inputFunction<ReadT, WriteT>(
156-
_initialValue?: ReadT,
157-
_opts?: InputOptions<ReadT, WriteT>): InputSignal<ReadT|undefined, WriteT> {
158-
return null!;
159-
}
150+
export interface InputFunction {
151+
<ReadT>(): InputSignal<ReadT|undefined>;
152+
<ReadT>(initialValue: ReadT, opts?: InputOptionsWithoutTransform<ReadT>): InputSignal<ReadT>;
153+
<ReadT, WriteT>(initialValue: ReadT, opts: InputOptionsWithTransform<ReadT, WriteT>):
154+
InputSignalWithTransform<ReadT, WriteT>;
160155

161-
export function inputRequiredFunction<ReadT>(opts?: InputOptionsWithoutTransform<ReadT>):
162-
InputSignal<ReadT>;
163-
export function inputRequiredFunction<ReadT, WriteT>(
164-
opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignal<ReadT, WriteT>;
165-
export function inputRequiredFunction<ReadT, WriteT>(_opts?: InputOptions<ReadT, WriteT>):
166-
InputSignal<ReadT, WriteT> {
167-
return null!;
156+
required: {
157+
<ReadT>(opts?: InputOptionsWithoutTransform<ReadT>): InputSignal<ReadT>;<ReadT, WriteT>(
158+
opts: InputOptionsWithTransform<ReadT, WriteT>): InputSignalWithTransform<ReadT, WriteT>;
159+
};
168160
}
169161

170-
export type InputFunction = typeof inputFunction&{required: typeof inputRequiredFunction};
171-
172-
export const input: InputFunction = (() => {
173-
(inputFunction as any).required = inputRequiredFunction;
174-
return inputFunction as InputFunction;
175-
})();
162+
export const input: InputFunction = null!;
176163

177164
export type ɵUnwrapInputSignalWriteType<Field> =
178-
Field extends InputSignal<unknown, infer WriteT>? WriteT : never;
165+
Field extends InputSignalWithTransform<unknown, infer WriteT>? WriteT : never;
179166
export type ɵUnwrapDirectiveSignalInputs<Dir, Fields extends keyof Dir> = {
180167
[P in Fields]: ɵUnwrapInputSignalWriteType<Dir[P]>
181168
};

packages/compiler-cli/src/ngtsc/typecheck/extended/checks/interpolated_signal_not_invoked/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class InterpolatedSignalCheck extends
3939

4040
function isSignal(symbol: ts.Symbol|undefined): boolean {
4141
return (symbol?.escapedName === 'WritableSignal' || symbol?.escapedName === 'Signal' ||
42-
symbol?.escapedName === 'InputSignal') &&
42+
symbol?.escapedName === 'InputSignal' ||
43+
symbol?.escapedName === 'InputSignalWithTransform') &&
4344
(symbol as any).parent.escapedName.includes('@angular/core');
4445
}
4546

0 commit comments

Comments
 (0)