---
description: subclass of Map that checks key/value types.
---

# TypedMap

[JS](../../..) ⟩ [value](../..) ⟩ [object](../../obj) ⟩ [class](..) ⟩ [example]() ⟩ TypedMap&#x20;

{% hint style="success" %}
key points：

* <mark style="color:red;">**must**</mark> call <mark style="color:yellow;">**superclass constructor**</mark> [`super()`](broken-reference) <mark style="color:red;">**before**</mark> using [**this**](../../../concept/execution-context/this).
* use [`super.method()`](broken-reference) to call <mark style="color:yellow;">**superclass methods**</mark> in subclass methods.
{% endhint %}

{% tabs %}
{% tab title="💾 程式" %}
* replit ⟩ [TypedMap](https://replit.com/@pegasusroe/TypedMap#TypedMap.js)

```javascript
// superclass
class TypedMap extends Map {
    
    // private properties
    #keyType;
    #valueType;
    
    // ⭐ subclass constructor
    constructor(keyType, valueType, entries) {

        // ⭐ must init new object with `super()` first❗
        super();            // ⭐ superclass constructor

        // ⭐ now `this` is accessable.
        this.#keyType = keyType;
        this.#valueType = valueType;
        
        // type-check/add entries if `entries` provided
        if (entries) {
            // subclass uses its method to help set key/value pairs,
            // make sure all properties are fully intialized before doing this❗
            entries.forEach(([key, value]) => this.set(key, value));
        }
    }

    // ⭐ override superclass method❗
    set(key, value) {
        // type check first, throw error if failed.
        this.#typecheck(key, value);
        // then set [key, value] using superclass method
        super.set(key, value);        // ⭐ superclass method
    }

    // check types
    #typecheck(key, value) {
        
        //  ⭐ destructuring private fields not allowed❓
        // ---------------------------------------------------------
        // const {#keyType: keyType, #valueType: valueType} = this;
        //        ^^^^^^^^ (⛔ SyntaxError: Unexpected identifier)

        const keyType = this.#keyType;
        const valueType = this.#valueType;
        
        if (typeof key !== keyType || typeof value !== valueType) 
            throw new TypeError(`[${key}:${value}] is not of type [${keyType}:${valueType}]`);
    }
}

// export
module.exports = TypedMap;
```
{% endtab %}

{% tab title="💈範例" %}
```javascript
const TypedMap = require('./TypedMap.js');

// test run
const dict = new TypedMap('string', 'string');
dict.set('hi', 'hello');
dict.get('hi')            // 'hello'

// dict.set(1, 'one');
// TypeError: [1:one] is not of type [string:string]

const a = new TypedMap('number', 'string', [
    [1, 'one'], [2, 'two'],
]);

a.get(1)                  // 'one'
```
{% endtab %}

{% tab title="📗 參考" %}
* [ ] [javascript-the-definitive-guide](../../../../master/ref/javascript-the-definitive-guide "mention") ⟩ 9.5.2 Subclasses with extends and super&#x20;
{% endtab %}
{% endtabs %}
