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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.