Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c9bbfc8

Browse files
committed
TypeScript 3.7 "asserts condition"
1 parent f2000a1 commit c9bbfc8

File tree

8 files changed

+60
-16
lines changed

8 files changed

+60
-16
lines changed

‎packages/react-form-with-constraints-material-ui/src/Material.tsx‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import {
2222
FieldFeedback as _FieldFeedback,
2323
FieldFeedbackBaseProps,
2424
Field,
25-
deepForEach
25+
deepForEach,
26+
assert
2627
} from 'react-form-with-constraints';
2728

2829
interface FormControlState {
@@ -67,7 +68,7 @@ export class FormControl extends React.Component<FormControlProps, FormControlSt
6768
}
6869
});
6970

70-
console.assert(
71+
assert(
7172
fieldNames.size === 1,
7273
// [...Set] vs Array.from(Set): the latter doesn't need downlevelIteration with IE
7374
`0 or multiple [name="*"] instead of 1: '${Array.from(fieldNames)}'`

‎packages/react-form-with-constraints/src/Async.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { FieldFeedbacks, FieldFeedbacksChildContext } from './FieldFeedbacks';
66
import { withValidateFieldEventEmitter } from './withValidateFieldEventEmitter';
77
import { FieldFeedbackValidation } from './FieldFeedbackValidation';
88
import { InputElement } from './InputElement';
9+
import { assert } from './assert';
910

1011
export enum Status {
1112
None,
@@ -123,7 +124,7 @@ export class Async<T>
123124
if (props.catch) element = props.catch(state.value);
124125
break;
125126
default:
126-
console.assert(false, `Unknown status: '${state.status}'`);
127+
assert(false, `Unknown status: '${state.status}'`);
127128
}
128129

129130
return element;

‎packages/react-form-with-constraints/src/EventEmitter.ts‎

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { assert } from './assert';
2+
13
// FIXME [Proposal: Variadic Kinds -- Give specific types to variadic functions](https://github.com/Microsoft/TypeScript/issues/5453)
24

35
type Listener<Args extends any[], ReturnType> = (...args: Args) => ReturnType | Promise<ReturnType>;
@@ -32,10 +34,10 @@ export class EventEmitter<ListenerArgs extends any[], ListenerReturnType> {
3234
const listeners = this.listeners.get(eventName);
3335

3436
// Assert disabled: an event can be emitted even without listeners
35-
//console.assert(listeners !== undefined, `Unknown event '${eventName}'`);
37+
//assert(listeners !== undefined, `Unknown event '${eventName}'`);
3638

3739
if (listeners !== undefined) {
38-
console.assert(listeners.length > 0, `No listener for event '${eventName}'`);
40+
assert(listeners.length > 0, `No listener for event '${eventName}'`);
3941
return listeners;
4042
}
4143
return [];
@@ -44,10 +46,7 @@ export class EventEmitter<ListenerArgs extends any[], ListenerReturnType> {
4446
addListener(eventName: string, listener: Listener<ListenerArgs, ListenerReturnType>) {
4547
if (!this.listeners.has(eventName)) this.listeners.set(eventName, []);
4648
const listeners = this.listeners.get(eventName)!;
47-
console.assert(
48-
listeners.indexOf(listener) === -1,
49-
`Listener already added for event '${eventName}'`
50-
);
49+
assert(listeners.indexOf(listener) === -1, `Listener already added for event '${eventName}'`);
5150
listeners.push(listener);
5251
}
5352

@@ -56,11 +55,11 @@ export class EventEmitter<ListenerArgs extends any[], ListenerReturnType> {
5655
// If any single listener has been added multiple times to the listener array for the specified eventName,
5756
// then removeListener must be called multiple times to remove each instance."
5857
removeListener(eventName: string, listener: Listener<ListenerArgs, ListenerReturnType>) {
59-
const listeners = this.listeners.get(eventName)!;
60-
console.assert(listeners !== undefined, `Unknown event '${eventName}'`);
58+
const listeners = this.listeners.get(eventName);
59+
assert(listeners !== undefined, `Unknown event '${eventName}'`);
6160

6261
const index = listeners.lastIndexOf(listener);
63-
console.assert(index > -1, `Listener not found for event '${eventName}'`);
62+
assert(index > -1, `Listener not found for event '${eventName}'`);
6463
listeners.splice(index, 1);
6564

6665
if (listeners.length === 0) this.listeners.delete(eventName);

‎packages/react-form-with-constraints/src/FieldsStore.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Field } from './Field';
22
import { EventEmitter } from './EventEmitter';
3+
import { assert } from './assert';
34

45
export enum FieldEvent {
56
Added = 'FIELD_ADDED',
@@ -11,13 +12,13 @@ export class FieldsStore extends EventEmitter<[Field | string], void> {
1112

1213
getField(fieldName: string) {
1314
const fields = this.fields.filter(_field => _field.name === fieldName);
14-
//console.assert(fields.length === 1, `Unknown field '${fieldName}'`);
15+
//assert(fields.length === 1, `Unknown field '${fieldName}'`);
1516
return fields.length === 1 ? fields[0] : undefined;
1617
}
1718

1819
addField(fieldName: string) {
1920
const fields = this.fields.filter(_field => _field.name === fieldName);
20-
console.assert(
21+
assert(
2122
fields.length === 0 || fields.length === 1,
2223
`Cannot have more than 1 field matching '${fieldName}'`
2324
);
@@ -37,7 +38,7 @@ export class FieldsStore extends EventEmitter<[Field | string], void> {
3738

3839
// We can have multiple FieldFeedbacks for the same field,
3940
// thus removeField() can be called multiple times
40-
//console.assert(fields.length === 1, `Unknown field '${fieldName}'`);
41+
//assert(fields.length === 1, `Unknown field '${fieldName}'`);
4142

4243
const index = this.fields.indexOf(fields[0]);
4344
if (index > -1) {

‎packages/react-form-with-constraints/src/FormWithConstraints.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { FieldsStore } from './FieldsStore';
1111
import { FieldFeedbackValidation } from './FieldFeedbackValidation';
1212
import { flattenDeep } from './flattenDeep';
1313
import { notUndefined } from './notUndefined';
14+
import { assert } from './assert';
1415

1516
export interface FormWithConstraintsChildContext {
1617
form: FormWithConstraints;
@@ -120,7 +121,7 @@ export class FormWithConstraints
120121
// Internal check that everything is OK
121122
// Can be temporary out of sync if the user rapidly change the input, in this case:
122123
// emitFieldWillValidateEvent() returns the result of the first change while the store already contains the final validations
123-
console.assert(
124+
assert(
124125
JSON.stringify(
125126
flattenDeep<FieldFeedbackValidation | undefined>(arrayOfArrays).filter(notUndefined)
126127
) /* validationsFromEmitValidateFieldEvent */ ===
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { assert } from './assert';
2+
3+
test('TypeScript "asserts condition"', () => {
4+
const foobar = (): number | string => 'foobar';
5+
6+
const str = foobar();
7+
assert(typeof str === 'string');
8+
9+
// Without assert(), TypeScript error: "Property 'includes' does not exist on type 'number'"
10+
str.includes('foo');
11+
});
12+
13+
test('console output', () => {
14+
expect.assertions(4);
15+
16+
const consoleSpy = jest.spyOn(console, 'assert').mockImplementation();
17+
18+
assert(false);
19+
20+
// "Unreachable code detected" for TypeScript
21+
22+
expect(consoleSpy).toHaveBeenCalledTimes(1);
23+
// Tests that it's not "false, undefined"
24+
expect(consoleSpy).toHaveBeenCalledWith(false);
25+
26+
assert(false, 'a message');
27+
expect(consoleSpy).toHaveBeenCalledTimes(2);
28+
expect(consoleSpy).toHaveBeenCalledWith(false, 'a message');
29+
30+
consoleSpy.mockRestore();
31+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/#assertion-functions
2+
export function assert(condition: boolean, message?: string): asserts condition {
3+
// error TS2569: Type 'IArguments' is not an array type or a string type.
4+
// Use compiler option '--downlevelIteration' to allow iterating of iterators.
5+
//console.assert(...arguments);
6+
7+
if (message === undefined) console.assert(condition);
8+
else console.assert(condition, message);
9+
}

‎packages/react-form-with-constraints/src/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ export * from './InputElement';
1616
export * from './Constructor';
1717
export * from './Input';
1818
export * from './deepForEach';
19+
export * from './assert';

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /