Skip to content

Commit

Permalink
Support using ObservableMap like it's a Record
Browse files Browse the repository at this point in the history
  • Loading branch information
jmeistrich committed Sep 16, 2024
1 parent 065e14c commit 76b8682
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
5 changes: 3 additions & 2 deletions src/observableTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ interface ObservableObjectFunctions<T = Record<string, any>> extends ObservableP

type MapKey<T extends Map<any, any> | WeakMap<any, any>> = Parameters<T['has']>[0];
type MapValue<T extends Map<any, any> | WeakMap<any, any>> = ReturnType<T['get']>;
type ObservableMap<T extends Map<any, any> | WeakMap<any, any>> = Omit<T, 'get' | 'size' | 'set'> &
Omit<ObservablePrimitive<T>, 'get' | 'size'> & {
export type ObservableMap<T extends Map<any, any> | WeakMap<any, any>> = Omit<T, 'get' | 'size' | 'set'> &
Omit<ObservablePrimitive<T>, 'get' | 'size'> &
Record<MapKey<T>, Observable<MapValue<T>>> & {
get(key: Parameters<T['get']>[0]): Observable<Parameters<T['set']>[1]>;
get(): T;
size: number;
Expand Down
8 changes: 8 additions & 0 deletions tests/mapset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ describe('Map default behavior', () => {
]),
);
});
test('Map get like object', () => {
const obs = observable({ test: new Map([['key', 'value']]) });

expect(isObservable(obs.test)).toEqual(true);
expect(isObservable(obs.test['key'])).toEqual(true);
expect(obs.test['key'].get()).toEqual('value');
expect(obs.test.get()).toBeInstanceOf(Map);
});
});

describe('Map is observable', () => {
Expand Down
24 changes: 20 additions & 4 deletions tests/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { expectTypeOf } from 'expect-type';
import { Observable, ObservableBoolean, ObservableParam, ObservablePrimitive } from '../src/observableTypes';
import {
Observable,
ObservableBoolean,
ObservableMap,
ObservableParam,
ObservablePrimitive,
} from '../src/observableTypes';
import { observable } from '../src/observable';

describe('observable', () => {
Expand Down Expand Up @@ -300,9 +306,19 @@ describe('with function', () => {
});
});

it('should infer Map', () => {
type GetState = Observable<Map<string, number>>['get'];
expectTypeOf<GetState>().returns.toEqualTypeOf<Map<string, number>>();
describe('with Map', () => {
it('should infer Map', () => {
type GetState = Observable<Map<string, number>>['get'];
expectTypeOf<GetState>().returns.toEqualTypeOf<Map<string, number>>();
});
it('should infer Map', () => {
type Type = Observable<Map<string, number>>;
expectTypeOf<Type>().toEqualTypeOf<ObservableMap<Map<string, number>>>();

const obs = observable({ test: new Map<string, number>() });
type Type2 = typeof obs.test;
expectTypeOf<Type2>().toEqualTypeOf<ObservableMap<Map<string, number>>>();
});
});

describe('with maybe undefined', () => {
Expand Down

0 comments on commit 76b8682

Please sign in to comment.