Reputation: 943
I have a function that takes an arbitrary number of classes.
function findObjects(...Classes) { ... }
All classes inherit from one Component
class. This function in a certain way searches for objects that are instances of these classes.
How to implement a template for functions with a variable number of parameters?
It should be something like this:
function findObjects(...Classes): [...Classes] { ... }
This is necessary for the correct definition of types and for the correct operation of intellisense.
Upvotes: 3
Views: 8547
Reputation: 1326
You can use rest parameters as described in the docs
interface A { }
class B implements A { }
class C implements A { }
function findObjects(...objs: A[]): A[] {
// function body
}
const obj1: B = {}
const obj2: C = {}
const result1 = findObjects(obj1);
const result2 = findObjects(obj1, obj2);
Hope that helps!
Upvotes: 1
Reputation: 20132
My answer follows what you have written:
All classes inherit from one Component class. This function in a certain way searches for objects that are instances of these classes.
So in the solution I am using some base class Component
and to search for some subclass members SubComponent
.
// some empty classes
class Component {}
class SubComponent extends Component {}
function findObjects(...args: Component[]): SubComponent[] {
return args.filter(el => el instanceof SubComponent); // do some by instanceof for example
}
// using
const results = findObjects(new Component(), new Component(), new SubComponent());
// results is an array only with SubComponent element
The definition of the function is following - findObjects(...args: Component[]): SubComponent[]
.
...args: Component[]
- we take as arguments unknown number of Component instances: SubComponent[]
- we return array of SubComponents
I would propose to change little bit definition of this, as we return array, then better would be to take also array:
function findObjects(arr: Component[]): SubComponent[] {
return arr.filter(el => el instanceof SubComponent); // do some instanceof for example
}
// using
const results = findObjects([new Component(), new Component(), new SubComponent()]);
// results is an array only with SubComponent element
Pay attention that now the argument is one - arr
but it is consistent with the output, we put array in, and take array out. Just a suggestion though.
Upvotes: 1
Reputation: 74500
You may want to have a look at tuple rest parameters, which are used to emulate functions with a variable number of parameters. A possible solution:
// We pass in a tuple of classes. This tuple is generically typed (type parameter T)
// { new(...arg: any): any } is constructor function type for a class
function findObjects<T extends { new(...arg: any): any }[]>(...cls: T): Partial<T> {
// search for objects that are instances of these classes; return filtered classes
}
class Component { c = "c" }
class A extends Component { a = "a" }
class B extends Component { b = "b" }
const res = findObjects(A, B) // [(typeof A | undefined)?, (typeof B | undefined)?]
For the return type I used Partial<T>
, which is a mapped tuple with optional elements of the passed in classes. It contains undefined
at an index, if the corresponding class item is filtered out by your findObjects
implementation (adjust the return type like you need it).
Upvotes: 2