Amin Mohamed Ajani Amin Mohamed Ajani - 2 months ago 7
TypeScript Question

Accept Array of Interfaces OR single interface in TypeScript

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.

Answer

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