Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: replace any with unknown, enable noImplicitAny #76

Merged
merged 1 commit into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ behaviors it depends on. To understand this, consider the following contrived
example.

```js
const lifted = lift((a, b, c, d) => a && b ? c : d, aB, bB, cB, dB);
const lifted = lift((a, b, c, d) => (a && b ? c : d), aB, bB, cB, dB);
```

Here the resulting behavior will _always_ depend on both `aB`, `bB`, `cB`,
Expand All @@ -725,7 +725,7 @@ it is just a "black box".
If, on the other hand, we use `moment`:

```js
const momented = moment((at) => at(aB) && at(bB) ? at(cB) : at(dB));
const momented = moment((at) => (at(aB) && at(bB) ? at(cB) : at(dB)));
```

Then `moment` can simply check which behaviors are actually sampled inside the
Expand All @@ -736,8 +736,7 @@ depends on `atB` and there is no need to recompute `momented` when any of the
other behaviors changes.

`moment` can also be very useful with behaviors nested inside behaviors. If
`persons` is a behavior of an array of persons and is of the type `Behavior<{
age: Behavior<number>, name: string }[]>` then the following code creates a
`persons` is a behavior of an array of persons and is of the type `Behavior<{ age: Behavior<number>, name: string }[]>` then the following code creates a
behavior that at any time is equal to the name of the first person in the array
whose age is greater than 20.

Expand Down
34 changes: 17 additions & 17 deletions src/behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export abstract class Behavior<A> extends Reactive<A, BListener>
constructor() {
super();
}
static is(a: any): a is Behavior<any> {
static is(a: unknown): a is Behavior<unknown> {
return isBehavior(a);
}
map<B>(fn: (a: A) => B): Behavior<B> {
Expand All @@ -48,7 +48,7 @@ export abstract class Behavior<A> extends Reactive<A, BListener>
ap<B>(f: Behavior<(a: A) => B>): Behavior<B> {
return new ApBehavior<A, B>(f, this);
}
lift<A extends any[], R>(
lift<A extends unknown[], R>(
f: (...args: A) => R,
...args: MapBehaviorTuple<A>
): Behavior<R> {
Expand Down Expand Up @@ -122,7 +122,7 @@ export abstract class Behavior<A> extends Reactive<A, BListener>
}
}

export function pushToChildren(t: number, b: Behavior<any>): void {
export function pushToChildren(t: number, b: Behavior<unknown>): void {
for (const child of b.children) {
child.pushB(t);
}
Expand All @@ -137,7 +137,7 @@ function refresh<A>(b: Behavior<A>, t: number) {
b.last = newValue;
}

export function isBehavior(b: any): b is Behavior<any> {
export function isBehavior<A>(b: unknown): b is Behavior<A> {
return (
(typeof b === "object" && "at" in b && !isPlaceholder(b)) ||
(isPlaceholder(b) && (b.source === undefined || isBehavior(b.source)))
Expand Down Expand Up @@ -238,7 +238,7 @@ export function at<B>(b: Behavior<B>, t?: number): B {
}

export class MapBehavior<A, B> extends Behavior<B> {
constructor(private parent: Behavior<any>, private f: (a: A) => B) {
constructor(private parent: Behavior<A>, private f: (a: A) => B) {
super();
this.parents = cons(parent);
}
Expand All @@ -250,7 +250,7 @@ export class MapBehavior<A, B> extends Behavior<B> {
class ApBehavior<A, B> extends Behavior<B> {
constructor(private fn: Behavior<(a: A) => B>, private val: Behavior<A>) {
super();
this.parents = cons<any>(fn, cons(val));
this.parents = cons<Behavior<((a: A) => B) | A>>(fn, cons(val));
}
update(_t: number): B {
return this.fn.last(this.val.last);
Expand All @@ -271,7 +271,7 @@ export function ap<A, B>(
return valB.ap(fnB);
}

export class LiftBehavior<A extends any[], R> extends Behavior<R> {
export class LiftBehavior<A extends unknown[], R> extends Behavior<R> {
constructor(private f: (...as: A) => R, private bs: MapBehaviorTuple<A>) {
super();
this.parents = fromArray(bs);
Expand Down Expand Up @@ -344,7 +344,7 @@ export function when(b: Behavior<boolean>): Now<Future<{}>> {

class SnapshotBehavior<A> extends Behavior<Future<A>> implements SListener<A> {
private node: Node<this> = new Node(this);
constructor(private parent: Behavior<A>, private future: Future<any>) {
constructor(private parent: Behavior<A>, private future: Future<unknown>) {
super();
if (future.state === State.Done) {
// Future has occurred at some point in the past
Expand Down Expand Up @@ -375,7 +375,7 @@ class SnapshotBehavior<A> extends Behavior<Future<A>> implements SListener<A> {

export function snapshotAt<A>(
b: Behavior<A>,
f: Future<any>
f: Future<unknown>
): Behavior<Future<A>> {
return new SnapshotBehavior(b, f);
}
Expand Down Expand Up @@ -505,14 +505,14 @@ export function freezeTo<A>(

export function freezeAtFrom<A>(
behavior: Behavior<A>,
shouldFreeze: Future<any>
shouldFreeze: Future<unknown>
): Behavior<Behavior<A>> {
return snapshotAt(behavior, shouldFreeze).map((f) => freezeTo(behavior, f));
}

export function freezeAt<A>(
behavior: Behavior<A>,
shouldFreeze: Future<any>
shouldFreeze: Future<unknown>
): Now<Behavior<A>> {
return sample(freezeAtFrom(behavior, shouldFreeze));
}
Expand Down Expand Up @@ -583,7 +583,7 @@ export function accum<A, B>(
return sample(accumFrom(f, initial, source));
}

export type AccumPair<A> = [Stream<any>, (a: any, b: A) => A];
export type AccumPair<A> = [Stream<unknown>, (a: unknown, b: A) => A];

function accumPairToApp<A>([stream, fn]: AccumPair<A>): Stream<(a: A) => A> {
return stream.map((a) => (b: A) => fn(a, b));
Expand All @@ -607,7 +607,7 @@ export function accumCombine<B>(
return sample(accumCombineFrom(pairs, initial));
}

const firstArg = <A>(a: A, _: any): A => a;
const firstArg = <A>(a: A, _: unknown): A => a;

/**
* Creates a Behavior whose value is the last occurrence in the stream.
Expand Down Expand Up @@ -638,8 +638,8 @@ export function stepper<B>(initial: B, steps: Stream<B>): Now<Behavior<B>> {
*/
export function toggleFrom(
initial: boolean,
turnOn: Stream<any>,
turnOff: Stream<any>
turnOn: Stream<unknown>,
turnOff: Stream<unknown>
): Behavior<Behavior<boolean>> {
return stepperFrom(initial, turnOn.mapTo(true).combine(turnOff.mapTo(false)));
}
Expand All @@ -652,8 +652,8 @@ export function toggleFrom(
*/
export function toggle(
initial: boolean,
turnOn: Stream<any>,
turnOff: Stream<any>
turnOn: Stream<unknown>,
turnOff: Stream<unknown>
): Now<Behavior<boolean>> {
return sample(toggleFrom(initial, turnOn, turnOff));
}
Expand Down
21 changes: 14 additions & 7 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { tick } from "./clock";

export type Time = number;

function isBehavior(b: any): b is Behavior<any> {
function isBehavior(b: unknown): b is Behavior<unknown> {
return typeof b === "object" && "at" in b;
}

Expand Down Expand Up @@ -40,9 +40,16 @@ export interface SListener<A> extends Child {
pushS(t: number, value: A): void;
}

export interface ParentBehavior<A> extends Parent<Child> {
readonly at?: () => A;
readonly last?: A;
}
export class PushOnlyObserver<A> implements BListener, SListener<A> {
node: Node<this> = new Node(this);
constructor(private callback: (a: A) => void, private source: Parent<Child>) {
constructor(
private callback: (a: A) => void,
private source: ParentBehavior<A>
) {
source.addListener(this.node, tick());
if (isBehavior(source) && source.state === State.Push) {
callback(source.at());
Expand All @@ -61,13 +68,13 @@ export class PushOnlyObserver<A> implements BListener, SListener<A> {
}

export type NodeParentPair = {
parent: Parent<any>;
node: Node<any>;
parent: Parent<unknown>;
node: Node<unknown>;
};

export abstract class Reactive<A, C extends Child> implements Child {
state: State;
parents: Cons<Parent<any>>;
parents: Cons<Parent<unknown>>;
listenerNodes: Cons<NodeParentPair> | undefined;
children: DoubleLinkedList<C> = new DoubleLinkedList();
constructor() {
Expand Down Expand Up @@ -110,7 +117,7 @@ export abstract class Reactive<A, C extends Child> implements Child {
for (const parent of this.parents) {
const node = new Node(this);
this.listenerNodes = cons({ node, parent }, this.listenerNodes);
parent.addListener(node as any, t);
parent.addListener(node, t);
newState = Math.max(newState, parent.state);
}
if (this.state === State.Inactive) {
Expand All @@ -134,7 +141,7 @@ export class CbObserver<A> implements BListener, SListener<A> {
private callback: (a: A) => void,
readonly handlePulling: PullHandler,
private time: Time,
readonly source: Parent<Child>
readonly source: ParentBehavior<A>
) {
source.addListener(this.node, tick());
if (source.state === State.Pull) {
Expand Down
2 changes: 1 addition & 1 deletion src/datastructures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class Cons<A> {
}
}

export const nil: Cons<any> = new Cons(undefined, undefined, true);
export const nil: Cons<undefined> = new Cons(undefined, undefined, true);

export function cons<A>(value: A, tail: Cons<A> = nil): Cons<A> {
return new Cons(value, tail, false);
Expand Down
12 changes: 6 additions & 6 deletions src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DomEventStream<A> extends ProducerStream<A> {
constructor(
private target: EventTarget,
private eventName: string,
private extractor: Extractor<any, EventTarget, A>
private extractor: Extractor<unknown, EventTarget, A>
) {
super();
}
Expand Down Expand Up @@ -61,12 +61,12 @@ export function streamFromEvent<
export function streamFromEvent<A>(
target: EventTarget,
eventName: string,
extractor: Extractor<any, EventTarget, A>
extractor: Extractor<unknown, EventTarget, A>
): Stream<A>;
export function streamFromEvent<A>(
target: EventTarget,
eventName: string,
extractor: Extractor<any, EventTarget, A> = id
extractor: Extractor<A, EventTarget, A> = id
): Stream<A> {
return new DomEventStream(target, eventName, extractor);
}
Expand All @@ -76,7 +76,7 @@ class DomEventBehavior<A> extends ProducerBehavior<A> {
private target: EventTarget,
private eventName: string,
private getter: (t: EventTarget) => A,
private extractor: Extractor<any, EventTarget, A>
private extractor: Extractor<unknown, EventTarget, A>
) {
super();
this.last = getter(target);
Expand Down Expand Up @@ -123,13 +123,13 @@ export function behaviorFromEvent<A>(
target: EventTarget,
eventName: string,
getter: (t: EventTarget) => A,
extractor: Extractor<any, EventTarget, A>
extractor: Extractor<unknown, EventTarget, A>
): Behavior<A>;
export function behaviorFromEvent<A>(
target: EventTarget,
eventName: string,
getter: (t: EventTarget) => A,
extractor: Extractor<any, EventTarget, A>
extractor: Extractor<unknown, EventTarget, A>
): Behavior<A> {
return new DomEventBehavior(target, eventName, getter, extractor);
}
Expand Down
27 changes: 14 additions & 13 deletions src/future.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ export type MapFutureTuple<A> = { [K in keyof A]: Future<A[K]> };
* promise.
*/
export abstract class Future<A> extends Reactive<A, SListener<A>>
implements Parent<SListener<any>> {
implements Parent<SListener<unknown>> {
// The value of the future. Often `undefined` until occurrence.
value: A;
constructor() {
super();
}
abstract pushS(t: number, val: any): void;
abstract pushS(t: number, val: unknown): void;
pull(): A {
throw new Error("Pull not implemented on future");
}
Expand Down Expand Up @@ -63,7 +63,7 @@ export abstract class Future<A> extends Reactive<A, SListener<A>>
return new OfFuture(b);
}
ap: <B>(f: Future<(a: A) => B>) => Future<B>;
lift<A extends any[], R>(
lift<A extends unknown[], R>(
f: (...args: A) => R,
...args: MapFutureTuple<A>
): Future<R> {
Expand All @@ -87,7 +87,7 @@ export abstract class Future<A> extends Reactive<A, SListener<A>>
}
}

export function isFuture(a: any): a is Future<any> {
export function isFuture(a: unknown): a is Future<unknown> {
return typeof a === "object" && "resolve" in a;
}

Expand All @@ -112,11 +112,11 @@ export class MapFuture<A, B> extends Future<B> {
}

export class MapToFuture<A> extends Future<A> {
constructor(public value: A, readonly parent: Future<any>) {
constructor(public value: A, readonly parent: Future<unknown>) {
super();
this.parents = cons(parent);
}
pushS(t: any, _val: any): void {
pushS(t: Time): void {
this.resolve(this.value, t);
}
}
Expand All @@ -127,21 +127,21 @@ export class OfFuture<A> extends Future<A> {
this.state = State.Done;
}
/* istanbul ignore next */
pushS(_: any): void {
pushS(): void {
throw new Error("A PureFuture should never be pushed to.");
}
}

export class NeverFuture extends Future<any> {
export class NeverFuture extends Future<never> {
constructor() {
super();
this.state = State.Done;
}
addListener(node: Node<SListener<any>>, t: number): State {
addListener(): State {
return State.Done;
}
/* istanbul ignore next */
pushS(_: any): void {
pushS(): void {
throw new Error("A NeverFuture should never be pushed to.");
}
}
Expand All @@ -164,7 +164,7 @@ export class LiftFuture<A> extends Future<A> {
this.missing = futures.length;
this.parents = fromArray(futures);
}
pushS(t: number, _val: any): void {
pushS(t: Time): void {
if (--this.missing === 0) {
// All the dependencies have occurred.
for (let i = 0; i < this.futures.length; ++i) {
Expand All @@ -182,6 +182,7 @@ export class FlatMapFuture<A, B> extends Future<B> implements SListener<A> {
super();
this.parents = cons(parent);
}
//FIXME: remove any by splitting listeners to accept A and forward it to B through f
pushS(t: number, val: any): void {
if (this.parentOccurred === false) {
// The first future occurred. We can now call `f` with its value
Expand All @@ -201,7 +202,7 @@ export class FlatMapFuture<A, B> extends Future<B> implements SListener<A> {
*/
export class SinkFuture<A> extends ActiveFuture<A> {
/* istanbul ignore next */
pushS(_t: number, _val: any): void {
pushS(): void {
throw new Error("A sink should not be pushed to.");
}
}
Expand Down Expand Up @@ -249,7 +250,7 @@ export class NextOccurrenceFuture<A> extends Future<A> implements SListener<A> {
super();
this.parents = cons(s);
}
pushS(t: number, val: any): void {
pushS(t: Time, val: A): void {
this.resolve(val, t);
}
}
Expand Down
Loading