Skip to content

Commit 78db110

Browse files
authored
Merge pull request #1930 from pimterry/symbol-map-keys
Allow Symbol keys in observable maps (fixes #1925)
2 parents 4451340 + 9f12565 commit 78db110

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
3+
* Allow symbol keys in `ObservableMap`, see [#1930](https://github.com/mobxjs/mobx/pull/1930) by [pimterry](https://github.com/pimterry)
4+
15
# 4.9.3
26

37
* Fixed `observable.set` compatibility with IE 11, see [#1917](https://github.com/mobxjs/mobx/pull/1917) by [kalmi](https://github.com/kalmi)

src/types/observablemap.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,12 @@ export class ObservableMap<K = any, V = any>
174174
if (entry) {
175175
entry.setNewValue(value)
176176
} else {
177-
entry = new ObservableValue(value, referenceEnhancer, `${this.name}.${key}?`, false)
177+
entry = new ObservableValue(
178+
value,
179+
referenceEnhancer,
180+
`${this.name}.${stringifyKey(key)}?`,
181+
false
182+
)
178183
this._hasMap.set(key, entry)
179184
}
180185
return entry
@@ -210,7 +215,7 @@ export class ObservableMap<K = any, V = any>
210215
const observable = new ObservableValue(
211216
newValue,
212217
this.enhancer,
213-
`${this.name}.${key}`,
218+
`${this.name}.${stringifyKey(key)}`,
214219
false
215220
)
216221
this._data.set(key, observable)
@@ -345,7 +350,8 @@ export class ObservableMap<K = any, V = any>
345350
toPOJO(): IKeyValueMap<V> {
346351
const res: IKeyValueMap<V> = {}
347352
for (const [key, value] of this) {
348-
res["" + key] = value
353+
// We lie about symbol key types due to https://github.com/Microsoft/TypeScript/issues/1863
354+
res[typeof key === "symbol" ? <any>key : stringifyKey(key)] = value
349355
}
350356
return res
351357
}
@@ -368,7 +374,7 @@ export class ObservableMap<K = any, V = any>
368374
this.name +
369375
"[{ " +
370376
Array.from(this.keys())
371-
.map(key => `${key}: ${"" + this.get(key)}`)
377+
.map(key => `${stringifyKey(key)}: ${"" + this.get(key)}`)
372378
.join(", ") +
373379
" }]"
374380
)
@@ -395,6 +401,11 @@ export class ObservableMap<K = any, V = any>
395401
}
396402
}
397403

404+
function stringifyKey(key: any): string {
405+
if (key && key.toString) return key.toString()
406+
else return new String(key).toString()
407+
}
408+
398409
/* 'var' fixes small-build issue */
399410
export const isObservableMap = createInstanceofPredicate("ObservableMap", ObservableMap) as (
400411
thing: any

test/base/map.js

+19-8
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,23 @@ test("map crud", function() {
3131
expect(m.has(k)).toBe(true)
3232
expect(m.get(k)).toBe("arrVal")
3333

34-
expect(mobx.keys(m)).toEqual(["1", 1, k])
35-
expect(mobx.values(m)).toEqual(["aa", "b", "arrVal"])
36-
expect(Array.from(m)).toEqual([["1", "aa"], [1, "b"], [k, "arrVal"]])
37-
expect(m.toJS()).toEqual(new Map([["1", "aa"], [1, "b"], [k, "arrVal"]]))
38-
expect(m.toPOJO()).toEqual({ "1": "b", arr: "arrVal" })
34+
var s = Symbol("test")
35+
expect(m.has(s)).toBe(false)
36+
expect(m.get(s)).toBe(undefined)
37+
m.set(s, "symbol-value")
38+
expect(m.get(s)).toBe("symbol-value")
39+
expect(m.get(s.toString())).toBe(undefined)
40+
41+
expect(mobx.keys(m)).toEqual(["1", 1, k, s])
42+
expect(mobx.values(m)).toEqual(["aa", "b", "arrVal", "symbol-value"])
43+
expect(Array.from(m)).toEqual([["1", "aa"], [1, "b"], [k, "arrVal"], [s, "symbol-value"]])
44+
expect(m.toJS()).toEqual(new Map([["1", "aa"], [1, "b"], [k, "arrVal"], [s, "symbol-value"]]))
45+
expect(m.toPOJO()).toEqual({ "1": "b", arr: "arrVal", [s]: "symbol-value" })
3946
expect(JSON.stringify(m)).toEqual('{"1":"b","arr":"arrVal"}')
40-
expect(m.toString()).toBe("ObservableMap@1[{ 1: aa, 1: b, arr: arrVal }]")
41-
expect(m.size).toBe(3)
47+
expect(m.toString()).toBe(
48+
"ObservableMap@1[{ 1: aa, 1: b, arr: arrVal, Symbol(test): symbol-value }]"
49+
)
50+
expect(m.size).toBe(4)
4251

4352
m.clear()
4453
expect(mobx.keys(m)).toEqual([])
@@ -56,9 +65,11 @@ test("map crud", function() {
5665
{ object: m, name: "1", newValue: "aa", oldValue: "a", type: "update" },
5766
{ object: m, name: 1, newValue: "b", type: "add" },
5867
{ object: m, name: ["arr"], newValue: "arrVal", type: "add" },
68+
{ object: m, name: s, newValue: "symbol-value", type: "add" },
5969
{ object: m, name: "1", oldValue: "aa", type: "delete" },
6070
{ object: m, name: 1, oldValue: "b", type: "delete" },
61-
{ object: m, name: ["arr"], oldValue: "arrVal", type: "delete" }
71+
{ object: m, name: ["arr"], oldValue: "arrVal", type: "delete" },
72+
{ object: m, name: s, oldValue: "symbol-value", type: "delete" }
6273
])
6374
})
6475

0 commit comments

Comments
 (0)