diff --git a/src/domain/session/rightpanel/MemberListViewModel.js b/src/domain/session/rightpanel/MemberListViewModel.js
index b75a3d1c..1633936a 100644
--- a/src/domain/session/rightpanel/MemberListViewModel.js
+++ b/src/domain/session/rightpanel/MemberListViewModel.js
@@ -47,7 +47,7 @@ export class MemberListViewModel extends ViewModel {
             this.nameDisambiguator.disambiguate(vm);
             return vm;
         }
-        const updater = (vm, params, newMember) => {
+        const updater = (params, vm, newMember) => {
             vm.updateFrom(newMember);
             this.nameDisambiguator.disambiguate(vm);
         };
diff --git a/src/observable/map/BaseObservableMap.ts b/src/observable/map/BaseObservableMap.ts
index c4f7daae..b2f63c03 100644
--- a/src/observable/map/BaseObservableMap.ts
+++ b/src/observable/map/BaseObservableMap.ts
@@ -29,7 +29,7 @@ export interface IMapObserver<K, V> {
 
 export type BaseObservableMapConfig<K, V> = {
     join(_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V>;
-    mapValues(_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap;
+    mapValues(_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap<K, V>;
     sortValues(_this: BaseObservableMap<K, V>, comparator?: (a: any, b: any) => number): SortedMapList;
     filterValues(_this: BaseObservableMap<K, V>, filter: (v: V, k: K) => boolean): FilteredMap<K, V>;
 }
@@ -67,7 +67,7 @@ export abstract class BaseObservableMap<K, V> extends BaseObservable<IMapObserve
     // to easily use the default implementation in a class that extends
     // this one (which is most likely what you want to do).
     abstract join(...otherMaps: Array<typeof this>): JoinedMap<K, V>;
-    abstract mapValues(mapper: any, updater?: (params: any) => void): MappedMap;
+    abstract mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>;
     abstract sortValues(comparator?: (a: any, b: any) => number): SortedMapList;
     abstract filterValues(filter: (v: V, k: K) => boolean): FilteredMap<K, V>;
 
diff --git a/src/observable/map/FilteredMap.ts b/src/observable/map/FilteredMap.ts
index c4810d9b..a9603d6d 100644
--- a/src/observable/map/FilteredMap.ts
+++ b/src/observable/map/FilteredMap.ts
@@ -39,7 +39,7 @@ export class FilteredMap<K, V> extends BaseObservableMap<K, V> {
         return this._config.join(this, ...otherMaps);
     }
 
-    mapValues(mapper: any, updater?: (params: any) => void): MappedMap{
+    mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>{
         return this._config.mapValues(this, mapper, updater);
     }
 
diff --git a/src/observable/map/JoinedMap.ts b/src/observable/map/JoinedMap.ts
index 6f285fd9..fbf2f39d 100644
--- a/src/observable/map/JoinedMap.ts
+++ b/src/observable/map/JoinedMap.ts
@@ -24,7 +24,7 @@ import {SubscriptionHandle} from "../BaseObservable"
 
 export class JoinedMap<K, V> extends BaseObservableMap<K, V> {
     protected _sources: BaseObservableMap<K, V>[];
-    private _config: BaseObservableMapConfig<K, V>
+    private _config: BaseObservableMapConfig<K, V>;
     private _subscriptions?: SourceSubscriptionHandler<K, V>[];
 
     constructor(sources: BaseObservableMap<K, V>[]) {
@@ -37,7 +37,7 @@ export class JoinedMap<K, V> extends BaseObservableMap<K, V> {
         return this._config.join(this, ...otherMaps);
     }
 
-    mapValues(mapper: any, updater?: (params: any) => void): MappedMap{
+    mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> {
         return this._config.mapValues(this, mapper, updater);
     }
 
diff --git a/src/observable/map/LogMap.ts b/src/observable/map/LogMap.ts
index 988aa71b..a287014a 100644
--- a/src/observable/map/LogMap.ts
+++ b/src/observable/map/LogMap.ts
@@ -42,7 +42,7 @@ export class LogMap<K, V> extends BaseObservableMap<K, V> {
         return this._config.join(this, ...otherMaps);
     }
 
-    mapValues(mapper: any, updater?: (params: any) => void): MappedMap {
+    mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> {
         return this._config.mapValues(this, mapper, updater);
     }
 
diff --git a/src/observable/map/MappedMap.js b/src/observable/map/MappedMap.ts
similarity index 57%
rename from src/observable/map/MappedMap.js
rename to src/observable/map/MappedMap.ts
index a6b65c41..ff522621 100644
--- a/src/observable/map/MappedMap.js
+++ b/src/observable/map/MappedMap.ts
@@ -14,49 +14,83 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import {BaseObservableMap} from "./BaseObservableMap";
+import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap";
+import {config} from "./config";
+import {JoinedMap} from "./JoinedMap.js";
+import {FilteredMap} from "./FilteredMap.js";
+import {SortedMapList} from "../list/SortedMapList.js";
+import {SubscriptionHandle} from "../BaseObservable";
+
 /*
 so a mapped value can emit updates on it's own with this._emitSpontaneousUpdate that is passed in the mapping function
 how should the mapped value be notified of an update though? and can it then decide to not propagate the update?
 */
-export class MappedMap extends BaseObservableMap {
-    constructor(source, mapper, updater) {
+export class MappedMap<K, V> extends BaseObservableMap<K, V> {
+    private _source: BaseObservableMap<K, V>;
+    private _mapper: Mapper<V>;
+    private _updater?: Updater<V>;
+    private _mappedValues: Map<K, V>;
+    private _subscription?: SubscriptionHandle;
+    private _config: BaseObservableMapConfig<K, V>
+
+    constructor(
+        source: BaseObservableMap<K, V>,
+        mapper: Mapper<V>,
+        updater?: Updater<V>
+    ) {
         super();
         this._source = source;
         this._mapper = mapper;
         this._updater = updater;
-        this._mappedValues = new Map();
+        this._mappedValues = new Map<K, V>();
+        this._config = config<K, V>();
     }
 
-    _emitSpontaneousUpdate(key, params) {
+    join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
+        return this._config.join(this, ...otherMaps);
+    }
+
+    mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V>{
+        return this._config.mapValues(this, mapper, updater);
+    }
+
+    sortValues(comparator?: (a: any, b: any) => number): SortedMapList {
+        return this._config.sortValues(this, comparator);
+    }
+
+    filterValues(filter: (v: V, k: K) => boolean): FilteredMap<K, V> {
+        return this._config.filterValues(this, filter);
+    }
+
+    _emitSpontaneousUpdate(key: K, params: any) {
         const value = this._mappedValues.get(key);
         if (value) {
             this.emitUpdate(key, value, params);
         }
     }
 
-    onAdd(key, value) {
+    onAdd(key: K, value: V) {
         const emitSpontaneousUpdate = this._emitSpontaneousUpdate.bind(this, key);
         const mappedValue = this._mapper(value, emitSpontaneousUpdate);
         this._mappedValues.set(key, mappedValue);
         this.emitAdd(key, mappedValue);
     }
 
-    onRemove(key/*, _value*/) {
+    onRemove(key: K/*, _value*/) {
         const mappedValue = this._mappedValues.get(key);
         if (this._mappedValues.delete(key)) {
-            this.emitRemove(key, mappedValue);
+            if (mappedValue) this.emitRemove(key, mappedValue);
         }
     }
 
-    onUpdate(key, value, params) {
+    onUpdate(key: K, value: V, params: any) {
         // if an update is emitted while calling source.subscribe() from onSubscribeFirst, ignore it
         if (!this._mappedValues) {
             return;
         }
         const mappedValue = this._mappedValues.get(key);
         if (mappedValue !== undefined) {
-            this._updater?.(mappedValue, params, value);
+            this._updater?.(params, mappedValue, value);
             // TODO: map params somehow if needed?
             this.emitUpdate(key, mappedValue, params);
         }
@@ -74,7 +108,7 @@ export class MappedMap extends BaseObservableMap {
 
     onUnsubscribeLast() {
         super.onUnsubscribeLast();
-        this._subscription = this._subscription();
+        if (this._subscription) this._subscription = this._subscription();
         this._mappedValues.clear();
     }
 
@@ -91,7 +125,14 @@ export class MappedMap extends BaseObservableMap {
         return this._mappedValues.size;
     }
 
-    get(key) {
+    get(key: K): V | undefined {
         return this._mappedValues.get(key);
     }
 }
+
+type Mapper<V> = (
+    value: V,
+    emitSpontaneousUpdate: any,
+) => V;
+
+type Updater<V> = (params: any, mappedValue?: V, value?: V) => void;
\ No newline at end of file
diff --git a/src/observable/map/ObservableMap.ts b/src/observable/map/ObservableMap.ts
index 7ee3d666..06776927 100644
--- a/src/observable/map/ObservableMap.ts
+++ b/src/observable/map/ObservableMap.ts
@@ -36,7 +36,7 @@ export class ObservableMap<K, V> extends BaseObservableMap<K, V> {
         return this._config.join(this, ...otherMaps);
     }
 
-    mapValues(mapper: any, updater?: (params: any) => void): MappedMap{
+    mapValues(mapper: any, updater?: (params: any) => void): MappedMap<K, V> {
         return this._config.mapValues(this, mapper, updater);
     }
 
diff --git a/src/observable/map/config.ts b/src/observable/map/config.ts
index a0a63014..c91cfe1a 100644
--- a/src/observable/map/config.ts
+++ b/src/observable/map/config.ts
@@ -30,7 +30,7 @@ export function config<K, V>(): BaseObservableMapConfig<K, V> {
         join: (_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V> => {
             return new JoinedMap([_this].concat(otherMaps));
         },
-        mapValues: (_this: BaseObservableMap<K, V>, mapper: any, updater?: (params: any) => void): MappedMap => {
+        mapValues: (_this: BaseObservableMap<K, V>, mapper: any, updater: (params: any) => void): MappedMap<K, V> => {
             return new MappedMap(_this, mapper, updater);
         },
         sortValues: (_this: BaseObservableMap<K, V>, comparator?: (a: any, b: any) => number): SortedMapList => {