Skip to content

Commit

Permalink
fix(core): generic inference for signal inputs may break with `--stri…
Browse files Browse the repository at this point in the history
…ctFunctionTypes` (angular#54652)

This commit fixes that the generic inference for signal inputs may break
with `--strictFunctionTypes`.

We are not using --strictFunctionTypes` in all tests, so function parameters are always
checked bivariantly- while in 1P function parameters are checked contravariantly. This
breaks sub-typing and e.g. `InputSignal<number>` is not a subtype of `InputSignalWithTransform<unknown, number>`.

Root cause is that the input signal captures the equality function that
is exclusively concerned with the `ReadT`. And `ReadT` is never equal, or a
supertype of unknown.

https://www.typescriptlang.org/play?#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgSSTAFcYBlBAcyUwBsB1BGACwBUpMkBndaAWwA8AJWCYAJqwA0celCbBWAPjgBvAFBw4Aei1xWACXxlEXOCzxQIEeNkzEuwAIRmAnmDxhMHPsFRRTXnjYzMDYANbAYnDYECgcAG5eCJwwtC7SAHIA8qxwAEYIALSJcilpAHQacMAAjsR0AFxwABSYTSLiUvntohIAlHAAvMp5VrSiSADcalUA+rNQvaw9ndOa8wDucqjLMtsK0wC+aqCQsIgoaFi4BESkFNR0wkuKVaCoSGKmhCTkVDQMJhsDjcXhQQQdCTSSFKVTHNQxbjwEBNH73f50RgsdicHj8ATEJBhJAQDZIaRIYh8PJoZSDKqU2i0ZyYb53P6PWgCSnU2nTKpaABUM00rDceAA5GiOQDuVSaVBFBKTHASfBWVwMXlxmYIK53HApeyHgCscDcWDBITiaTyar5bSJZVReLTBB0HAwJZ3LAXIbavVaMrAhcYnxPDAENrgM7NHpxYbWk0eQrpHlkw6oANhvkxhNlQhTGq4BqtTqYHqYAmJUm4NaSWS00167bsyM85wnVU4-H3G6PZ5vL40KYJZhg59DeOS4tQxBw5hI9HYz2XQaJS2yQWi9YS1xNY9o7r9ZKU2gnc0AEwzDTZVgAUSaABF7wAFe8ZF8ZXJZDJwAAGhSFFwMByNgMAAGKEuBCCxGKfb-nA6C0JglArqugpaEAA

PR Close angular#54652
  • Loading branch information
devversion authored and pkozlowski-opensource committed Mar 4, 2024
1 parent 5e32a77 commit 78e6911
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/compiler-cli/src/ngtsc/testing/fake_core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export interface InputFunction {
export const input: InputFunction = null!;

export type ɵUnwrapInputSignalWriteType<Field> =
Field extends InputSignalWithTransform<unknown, infer WriteT>? WriteT : never;
Field extends InputSignalWithTransform<any, infer WriteT>? WriteT : never;
export type ɵUnwrapDirectiveSignalInputs<Dir, Fields extends keyof Dir> = {
[P in Fields]: ɵUnwrapInputSignalWriteType<Dir[P]>
};
Expand Down
14 changes: 12 additions & 2 deletions packages/compiler-cli/src/ngtsc/typecheck/test/test_case_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import ts from 'typescript';

import {TypeCheckingConfig} from '../api';
import {diagnose} from '../testing';

Expand Down Expand Up @@ -54,7 +56,7 @@ export interface TestCase {
* Diagnoses the given test case, by constructing the test TypeScript file
* and running the type checker on it.
*/
export function typeCheckDiagnose(c: TestCase) {
export function typeCheckDiagnose(c: TestCase, compilerOptions?: ts.CompilerOptions) {
const inputs = c.inputs ?? {};
const outputs = c.outputs ?? {};

Expand Down Expand Up @@ -124,7 +126,7 @@ export function typeCheckDiagnose(c: TestCase) {
.map(([name]) => name),
},
],
undefined, c.options);
undefined, c.options, compilerOptions);

expect(messages).toEqual(c.expected);
}
Expand All @@ -136,4 +138,12 @@ export function generateDiagnoseJasmineSpecs(cases: TestCase[]): void {
typeCheckDiagnose(c);
});
}

describe('with `--strict`', () => {
for (const c of cases) {
(c.focus ? fit : it)(c.id, () => {
typeCheckDiagnose(c, {strict: true});
});
}
});
}
2 changes: 1 addition & 1 deletion packages/core/src/authoring/input/input_type_checking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {InputSignalWithTransform} from './input_signal';

/** Retrieves the `WriteT` of an `InputSignal` and `InputSignalWithTransform`. */
export type ɵUnwrapInputSignalWriteType<Field> =
Field extends InputSignalWithTransform<unknown, infer WriteT>? WriteT : never;
Field extends InputSignalWithTransform<any, infer WriteT>? WriteT : never;

/**
* Unwraps all `InputSignal`/`InputSignalWithTransform` class fields of
Expand Down

0 comments on commit 78e6911

Please sign in to comment.