Add type annotations to ObservableValue

This commit is contained in:
Danila Fedorin 2021-09-29 17:43:17 -07:00
parent a7360f409e
commit ab6ce62551

View file

@ -18,18 +18,16 @@ import {AbortError} from "../utils/error.js";
import {BaseObservable} from "./BaseObservable"; import {BaseObservable} from "./BaseObservable";
// like an EventEmitter, but doesn't have an event type // like an EventEmitter, but doesn't have an event type
export class BaseObservableValue extends BaseObservable { export abstract class BaseObservableValue<T> extends BaseObservable<(value: T) => void> {
emit(argument) { emit(argument: T) {
for (const h of this._handlers) { for (const h of this._handlers) {
h(argument); h(argument);
} }
} }
get() { abstract get(): T;
throw new Error("unimplemented");
}
waitFor(predicate) { waitFor(predicate: (value: T) => boolean): IWaitHandle<T> {
if (predicate(this.get())) { if (predicate(this.get())) {
return new ResolvedWaitForHandle(Promise.resolve(this.get())); return new ResolvedWaitForHandle(Promise.resolve(this.get()));
} else { } else {
@ -38,8 +36,17 @@ export class BaseObservableValue extends BaseObservable {
} }
} }
class WaitForHandle { interface IWaitHandle<T> {
constructor(observable, predicate) { promise: Promise<T>;
dispose(): void;
}
class WaitForHandle<T> implements IWaitHandle<T> {
private _promise: Promise<T>
private _reject: ((reason?: any) => void) | null;
private _subscription: (() => void) | null;
constructor(observable: BaseObservableValue<T>, predicate: (value: T) => boolean) {
this._promise = new Promise((resolve, reject) => { this._promise = new Promise((resolve, reject) => {
this._reject = reject; this._reject = reject;
this._subscription = observable.subscribe(v => { this._subscription = observable.subscribe(v => {
@ -52,7 +59,7 @@ class WaitForHandle {
}); });
} }
get promise() { get promise(): Promise<T> {
return this._promise; return this._promise;
} }
@ -68,25 +75,24 @@ class WaitForHandle {
} }
} }
class ResolvedWaitForHandle { class ResolvedWaitForHandle<T> implements IWaitHandle<T> {
constructor(promise) { constructor(public promise: Promise<T>) {}
this.promise = promise;
}
dispose() {} dispose() {}
} }
export class ObservableValue extends BaseObservableValue { export class ObservableValue<T> extends BaseObservableValue<T> {
constructor(initialValue) { private _value: T;
constructor(initialValue: T) {
super(); super();
this._value = initialValue; this._value = initialValue;
} }
get() { get(): T {
return this._value; return this._value;
} }
set(value) { set(value: T): void {
if (value !== this._value) { if (value !== this._value) {
this._value = value; this._value = value;
this.emit(this._value); this.emit(this._value);
@ -94,8 +100,10 @@ export class ObservableValue extends BaseObservableValue {
} }
} }
export class RetainedObservableValue extends ObservableValue { export class RetainedObservableValue<T> extends ObservableValue<T> {
constructor(initialValue, freeCallback) { private _freeCallback: () => void;
constructor(initialValue: T, freeCallback: () => void) {
super(initialValue); super(initialValue);
this._freeCallback = freeCallback; this._freeCallback = freeCallback;
} }
@ -109,7 +117,7 @@ export class RetainedObservableValue extends ObservableValue {
export function tests() { export function tests() {
return { return {
"set emits an update": assert => { "set emits an update": assert => {
const a = new ObservableValue(); const a = new ObservableValue<number>(0);
let fired = false; let fired = false;
const subscription = a.subscribe(v => { const subscription = a.subscribe(v => {
fired = true; fired = true;
@ -140,7 +148,7 @@ export function tests() {
assert.strictEqual(a.get(), 6); assert.strictEqual(a.get(), 6);
}, },
"waitFor promise rejects when disposed": async assert => { "waitFor promise rejects when disposed": async assert => {
const a = new ObservableValue(); const a = new ObservableValue<number>(0);
const handle = a.waitFor(() => false); const handle = a.waitFor(() => false);
Promise.resolve().then(() => { Promise.resolve().then(() => {
handle.dispose(); handle.dispose();