I'm trying to write a type which acts as a function signature that allows to have to different set of parameters:
This is the example: Link to TS PlaGround. I also copy the code here just in case:
type T1<Tentity> = (predicate: ((entity: Tentity) => Tentity | void)) => void;
type T2<TEntity> = (propertyName: keyof TEntity, newValue: unknown) => void;
type TCommon<TEntity> = T1<TEntity> | T2<TEntity>;
interface IEntity {
name: string;
surname: boolean;
}
const entity : IEntity = { name: 'Foo', surname: true };
const method : TCommon<IEntity> = (param1, param2) => {
if (typeof(param1) === 'function') {
param1(entity);
}
else {
(entity[param1] as any)= param2;
}
}
method('name', 'Bar');
method((entity) => { entity.name = 'Bar'});
As you can see, I expect both calls of method
to work correctly.
From what I think, TypeScript/IntelliSense should be smart enough to make this reasoning:
function
, then we have a T1
, therefore I don't even need the second parameter.T2
, thus I expect a second parameter as well.Unfortunately, this is not what's happening: it seems TypeScript cannot "believe" that param1 can also be a function:
I'm pretty sure this can be done because we have the function overload, but I've been able to use them only inside a class
. But it's basically the same thing, expect in this case I'm defining the method
as a global variable.
Use an interface to describe a set of call signatures:
interface TCommon<TEntity> {
(predicate: ((entity: TEntity) => TEntity | void)): void
(propertyName: keyof TEntity, newValue: unknown): void;
}
But we aren't quite done yet. The second parameter is optional in the sense that the first overload doesn't need a second parameter but the second overload does.
So we mark the second parameter as optional:
const method: TCommon<IEntity> = (param1, param2?: unknown) => {
And that's it.