Is it possible to retrieve specific type from mixed array using typed function?
public plugins: (Tool|Service)[] = [];
getTools(): Tool[]{
return this.plugins.filter(t => t instanceof Tool);
}
So far I have no luck. Typescript is throwing following message
TS2322: Type '(Tool | Service)[]' is not assignable to type 'Tool[]'. Property 'onclick' is missing in type 'Service'.
Is there any way how I can set function type to Tool[]
here?
Here is full code:
interface Required {
id: string
title: string
owner: string
type: 'user' | 'admin'
}
class P {
id; title; owner; type;
constructor(config: Required){
this.id = config.id || 'uniqid';
this.title = config.title || 'Title';
this.owner = config.owner || 'user';
this.type = config.type;
}
}
interface ToolRequired extends Required{
onclick: () => void
}
class Tool extends P {
onclick;
constructor(config = {} as ToolRequired){
super(config);
this.type = 'tool';
this.onclick = config.onclick
}
}
class Service extends P {
constructor(config = {} as Required){
super(config);
this.type = 'service'
}
}
class Storag {
static types = {
tool: Tool,
service: Service,
undefined: Tool,
};
public plugins: (Tool|Service)[] = [];
setPlugin(config = {} as Required){
const Type = Storag.types[config.type];
this.plugins.push( new Type(config) );
}
getTools(): Tool[]{
return this.plugins.filter(t => t instanceof Tool);
}
}
Just tack on an as Tool[]
at the end.
public plugins: (Tool|Service)[] = [];
getTools(): Tool[]{
return this.plugins.filter(t => t instanceof Tool) as Tool[]; // << here
}
The reason you need to do this is because the Typescript compiler isn't smart enough to know that when you do such a filter it will only return Tool
s. A .filter
on any array will usually return the same type as the previous array, which is what the compiler assumes here - a Tool|Service
array.
The compiler is smart enough to know, however, that a Tool|Service
can be reduced down to only Tool
s - as such, you can do an as Tool[]
at the end to tell the compiler I know what I'm doing - the type that ".filter" returns will only be Tools here
, and the compiler will listen and respect it as such.
You can read more about the as
keyword here: https://www.typescriptlang.org/docs/handbook/basic-types.html (scroll down or search for "Type assertions").