Skip to content

Commit f5c7e88

Browse files
mheverymatsko
authored andcommitted
refactor(core): Take advantage of 'assert functions' for ngDevMode asserts (angular#35964)
As of TypeScript 3.7, TypeScript supports [Assert Functions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions). This change adds assert types to our `assert*` functions. We can't fully take advantage of this due to [Assert functions do not constraint type when they are guarded by a truthy expression.](microsoft/TypeScript#37295) PR Close angular#35964
1 parent 15f8afa commit f5c7e88

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

packages/core/src/render3/assert.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@
99
import {assertDefined, assertEqual, throwError} from '../util/assert';
1010

1111
import {getComponentDef, getNgModuleDef} from './definition';
12+
import {LContainer} from './interfaces/container';
13+
import {DirectiveDef} from './interfaces/definition';
1214
import {TNode} from './interfaces/node';
1315
import {isLContainer, isLView} from './interfaces/type_checks';
1416
import {LView, TVIEW, TView} from './interfaces/view';
1517

18+
// [Assert functions do not constraint type when they are guarded by a truthy
19+
// expression.](https://github.com/microsoft/TypeScript/issues/37295)
20+
21+
1622
export function assertTNodeForLView(tNode: TNode, lView: LView) {
1723
tNode.hasOwnProperty('tView_') && assertEqual(
1824
(tNode as any as{tView_: TView}).tView_, lView[TVIEW],
@@ -50,20 +56,21 @@ export function assertDataNext(lView: LView, index: number, arr?: any[]) {
5056
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
5157
}
5258

53-
export function assertLContainerOrUndefined(value: any): void {
59+
export function assertLContainerOrUndefined(value: any): asserts value is LContainer|undefined|
60+
null {
5461
value && assertEqual(isLContainer(value), true, 'Expecting LContainer or undefined or null');
5562
}
5663

57-
export function assertLContainer(value: any): void {
64+
export function assertLContainer(value: any): asserts value is LContainer {
5865
assertDefined(value, 'LContainer must be defined');
5966
assertEqual(isLContainer(value), true, 'Expecting LContainer');
6067
}
6168

62-
export function assertLViewOrUndefined(value: any): void {
69+
export function assertLViewOrUndefined(value: any): asserts value is LView|null|undefined {
6370
value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null');
6471
}
6572

66-
export function assertLView(value: any) {
73+
export function assertLView(value: any): asserts value is LView {
6774
assertDefined(value, 'LView must be defined');
6875
assertEqual(isLView(value), true, 'Expecting LView');
6976
}
@@ -82,7 +89,7 @@ export function assertFirstUpdatePass(tView: TView, errMessage?: string) {
8289
* This is a basic sanity check that an object is probably a directive def. DirectiveDef is
8390
* an interface, so we can't do a direct instanceof check.
8491
*/
85-
export function assertDirectiveDef(obj: any) {
92+
export function assertDirectiveDef<T>(obj: any): asserts obj is DirectiveDef<T> {
8693
if (obj.type === undefined || obj.selectors == undefined || obj.inputs === undefined) {
8794
throwError(
8895
`Expected a DirectiveDef/ComponentDef and this object does not seem to have the expected shape.`);

packages/core/src/render3/node_assert.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@
77
*/
88

99
import {assertDefined, assertEqual} from '../util/assert';
10-
import {TNode, TNodeType} from './interfaces/node';
1110

12-
export function assertNodeType(tNode: TNode, type: TNodeType) {
11+
import {TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeType, TProjectionNode} from './interfaces/node';
12+
13+
export function assertNodeType(
14+
tNode: TNode, type: TNodeType.Container): asserts tNode is TContainerNode;
15+
export function assertNodeType(
16+
tNode: TNode, type: TNodeType.Element): asserts tNode is TElementNode;
17+
export function assertNodeType(
18+
tNode: TNode, type: TNodeType.ElementContainer): asserts tNode is TElementContainerNode;
19+
export function assertNodeType(
20+
tNode: TNode, type: TNodeType.IcuContainer): asserts tNode is TIcuContainerNode;
21+
export function assertNodeType(
22+
tNode: TNode, type: TNodeType.Projection): asserts tNode is TProjectionNode;
23+
export function assertNodeType(tNode: TNode, type: TNodeType.View): asserts tNode is TContainerNode;
24+
export function assertNodeType(tNode: TNode, type: TNodeType): asserts tNode is TNode {
1325
assertDefined(tNode, 'should be called with a TNode');
1426
assertEqual(tNode.type, type, `should be a ${typeName(type)}`);
1527
}
1628

17-
export function assertNodeOfPossibleTypes(tNode: TNode, ...types: TNodeType[]) {
29+
export function assertNodeOfPossibleTypes(tNode: TNode, ...types: TNodeType[]): void {
1830
assertDefined(tNode, 'should be called with a TNode');
1931
const found = types.some(type => tNode.type === type);
2032
assertEqual(

packages/core/src/util/assert.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@
1212

1313
import {stringify} from './stringify';
1414

15-
export function assertNumber(actual: any, msg: string) {
15+
export function assertNumber(actual: any, msg: string): asserts actual is number {
1616
if (!(typeof actual === 'number')) {
1717
throwError(msg, typeof actual, 'number', '===');
1818
}
1919
}
2020

21-
export function assertNumberInRange(actual: any, minInclusive: number, maxInclusive: number) {
21+
export function assertNumberInRange(
22+
actual: any, minInclusive: number, maxInclusive: number): asserts actual is number {
2223
assertNumber(actual, 'Expected a number');
2324
assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to');
2425
assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to');
2526
}
2627

27-
export function assertString(actual: any, msg: string) {
28+
export function assertString(actual: any, msg: string): asserts actual is string {
2829
if (!(typeof actual === 'string')) {
2930
throwError(msg, actual === null ? 'null' : typeof actual, 'string', '===');
3031
}
@@ -36,13 +37,13 @@ export function assertEqual<T>(actual: T, expected: T, msg: string) {
3637
}
3738
}
3839

39-
export function assertNotEqual<T>(actual: T, expected: T, msg: string) {
40+
export function assertNotEqual<T>(actual: T, expected: T, msg: string): asserts actual is T {
4041
if (!(actual != expected)) {
4142
throwError(msg, actual, expected, '!=');
4243
}
4344
}
4445

45-
export function assertSame<T>(actual: T, expected: T, msg: string) {
46+
export function assertSame<T>(actual: T, expected: T, msg: string): asserts actual is T {
4647
if (!(actual === expected)) {
4748
throwError(msg, actual, expected, '===');
4849
}
@@ -54,25 +55,26 @@ export function assertNotSame<T>(actual: T, expected: T, msg: string) {
5455
}
5556
}
5657

57-
export function assertLessThan<T>(actual: T, expected: T, msg: string) {
58+
export function assertLessThan<T>(actual: T, expected: T, msg: string): asserts actual is T {
5859
if (!(actual < expected)) {
5960
throwError(msg, actual, expected, '<');
6061
}
6162
}
6263

63-
export function assertLessThanOrEqual<T>(actual: T, expected: T, msg: string) {
64+
export function assertLessThanOrEqual<T>(actual: T, expected: T, msg: string): asserts actual is T {
6465
if (!(actual <= expected)) {
6566
throwError(msg, actual, expected, '<=');
6667
}
6768
}
6869

69-
export function assertGreaterThan<T>(actual: T, expected: T, msg: string) {
70+
export function assertGreaterThan<T>(actual: T, expected: T, msg: string): asserts actual is T {
7071
if (!(actual > expected)) {
7172
throwError(msg, actual, expected, '>');
7273
}
7374
}
7475

75-
export function assertGreaterThanOrEqual<T>(actual: T, expected: T, msg: string) {
76+
export function assertGreaterThanOrEqual<T>(
77+
actual: T, expected: T, msg: string): asserts actual is T {
7678
if (!(actual >= expected)) {
7779
throwError(msg, actual, expected, '>=');
7880
}
@@ -98,7 +100,7 @@ export function throwError(msg: string, actual?: any, expected?: any, comparison
98100
(comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`));
99101
}
100102

101-
export function assertDomNode(node: any) {
103+
export function assertDomNode(node: any): asserts node is Node {
102104
// If we're in a worker, `Node` will not be defined.
103105
assertEqual(
104106
(typeof Node !== 'undefined' && node instanceof Node) ||

0 commit comments

Comments
 (0)