1

Really new in TypeScript. I have an array of presets that the user can add or modify existing ones. Since it has a couple of keys only, I made an interface.

interface IStylePreset {
    type : string;
    backgroundColor : string;
    color? : string
}

And the implementation is here:

static stylePresets : Array<IStylePreset> = [
    { type: "default", backgroundColor: "#37474f" , color: "#ECEFF1"},
    { type: "success", backgroundColor: "#37474f", color: "#ECEFF1" },
    { type: "error", backgroundColor: "#d32f2f", color: "#EEE"}
];

Now I have a config function that takes a custom preset to either change existing presets or add new ones.

static config = {
    types(newPresets) : void {
        newPresets = [].concat(newPresets);
        for(var i = 0, len = newPresets.length, current; i< len; i++){
            var pos = Message.Util.find(Message.stylePresets, newPresets[i].type)
            current = newPresets[i];
            if(pos !== -1) for(var key in current) Message.stylePresets[pos][key] = current[key];
            else Message.stylePresets[Message.stylePresets.length] = current;
            }
        }
    };

The problem is, I can't figure out what to specify in the type of newPresets since it's accepting both an array of objects and as well as a single object (which makes into a single element array newPresets = [].concat(newPresets);).

I'm trying to learn TypeScript and I don't know if what I'm doing is right. Can someone please help me out here? Further reading material or docs would be gold.

1
  • It was pointed out that the question is a duplicate so I'm voting it down. Commented Sep 29, 2016 at 10:12

2 Answers 2

1

Use a TypeScript union type: IStylePreset | IStylePreset[].

In the function body you can check with Array.isArray() whether an array or a single instance was passed. Actually, in this case, concat() does already check internally whether an array or an instance is concatenated so the solution is simple:

E.g.:

class Config {
    private presets: IStylePreset[] = [];

    public addPresets(presetOrArray: IStylePreset | IStylePreset[]) {
        // Concat will concat either Array or instance
        this.presets = this.presets.concat(presetOrArray);
    }

    public getPresets(): IStylePreset[] {
        return this.presets;
    }
}

let config = new Config();
config.addPresets(stylePresets);
config.addPresets(stylePresets[0]);
console.log(config.getPresets().length); // prints 4
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! I was actually thinking on the same lines.. But I'm trying to avoid isArray when I can go for [].concat. Its 43% faster on chrome plus we stay dry because the code will be the same in both if and else except a few changes. Can you please confirm whether types(newPresets : IStylePreset | Array<IStylePreset>) will work? The compiler says its clean but I still am not sure whether it's correct or not.. Tried looking at the docs but can't find it..
Yes, IStylePreset[] and Array<IStylePreset> are just two different notations for the same thing. Good point regarding concat. Its actually more efficient than pushing in a foreEach-loop. I've modified the example above accordingly. You still need isArray to check whether an array or a single instance was passed.
if a single instance is passed, concat will make it into an array. if an array is passed, [].concat results in no changes. +1ing the answer. Will accept it after a while to see if there are better performance solutions to this. Thanks man!
Thanks for pointing this out. One newer stops learning new things when answering questions... In that case, the call to isArray is indeed unnecessary. Example adapted.
1

You could either:

1) use the any type like this: types(newPresets : any)

or

2) keep the IStylePreset[] type (e.g. types(newPresets : IStylePreset[]) and when passing a single object just wrap it in an array like this: config.types([{ type: "default", backgroundColor: "#37474f" , color: "#ECEFF1"}]);

3 Comments

Thanks. I'm trying to avoid any. I think I may have found an alternative solution by using types(newPresets : IStylePreset | Array<IStylePreset>) : void {... The compiler says its clean but I don't know if this is right.. Can you confirm it?
That sounds ok from the method signature point of view. Also, I just saw that your question is actually already answered here: stackoverflow.com/questions/35749833/…
Just saw it. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.