2

I'm not yet familiar with Typescript, and I'm having troubles to define a simple array.

My goal is to have an array where the key is a string and its values are of types Sound.

I have defined an interface like that:

interface SoundsArrayType {
    [key: string]: Sound;
}

Then:

class SoundManager {
    private sounds: SoundsArrayType;

    constructor() {
      // error: Type 'undefined[]' is not assignable to type 'SoundsArrayType'.
      if(!this.sounds) this.sounds = [];
    }

    pauseAll() {
        for(let sound of this.sounds) {
            // error: Type 'SoundsArrayType' must have a '[Symbol.iterator]()' method that returns an iterator.
            sound.pause();
        }
    }
}

I'm not sure how to fix these errors. I read the Interfaces page from the Typescript site but I'm still stuck.

3
  • Arrays in JavaScript/TypeScript don't have arbitrary string keys. The type SoundsArrayType is not an array but a dictionary-like object. Don't assign [] to it; assign {} instead. Don't try iterating over it directly; if you are using ES2017 or above, you can iterate over Object.values(this.sounds) instead of this.sounds. Commented May 16, 2019 at 1:29
  • 1
    Thanks @jcalz, I think I confused myself with PHP arrays where you can use them as dictionaries. Commented May 16, 2019 at 4:03
  • The truth is subtler than I made it out to be, of course. Arrays in JavaScript are objects, which generally do support expando properties. So in practice you can add arbitrary string-keyed properties to them. But you shouldn't expect an array to have such properties, and TypeScript's static type system warns you about that. Commented May 16, 2019 at 13:07

2 Answers 2

2

My goal is to have an array where the key is a string and its values are of types Sound.

This might be a good use for the the Map type.

Here it is in TypeScript.

type Sound = {
    name: string;
};

const myMap = new Map<string, Sound>();
myMap.set('dog', { name: 'woof' });
myMap.set('cat', { name: 'meow' });
myMap.set('fox', { name: 'what does the fox say?!?!' });

Here it is in JavaScript without the type checking.

const myMap = new Map();

myMap.set('dog', { name: 'woof' });
myMap.set('cat', { name: 'meow' });
myMap.set('fox', { name: 'what does the fox say?!?!' });

for (let value of myMap.values()) { 
    console.log(value.name);
}

for (let key of myMap.keys()) { 
    console.log(key);
}

for (let [key, value] of myMap) { 
    console.log(key + ':' + value.name);
}

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I confused with PHP arrays which act like dictionaries. I'm going to try with Map, it seems to be the way to accomplish what I want.
0
interface Sounds { // It is not an array
    [key: string]: Sound;
}

Then:

class SoundManager {
    private sounds: Sounds = {}; // Just assign an empty object to it

    constructor() { }

    pauseAll() {
        for(let key of this.sounds.keys) {
            this.sounds[key].pause();
        }
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.