I am writing mocha
tests.
I have 2 interfaces(TestInterface1, TestInterface2
). They have functions described on it such as:
TestInterface1
- Func1, Func2
TestInterface2
- Func1, Func2, Func3
In my tests, I have a class Test
that sometimes ends up to be of TestInterface1
but might still have a function Func3
. It's like in run-time, can't decide which interface it belongs to.
Let's say it ended up to be TestInterface1
. Now, it still could have Func3
, but because of the interface, when I call function, it says that Function doesn't exist even though it does. How can I still figure out that Func3
still exists on the Test
which is of TestInterface1
?
// ------
// stub declaration - you have defined those interfaces already
interface TestInterface1 {
Func1: Function
Func2: Function
}
interface TestInterface2 {
Func1: Function
Func2: Function
Func3: Function
}
// assuming you have value already
declare const yourInterface: TestInterface1 | TestInterface2;
// ------
// and the IMPORTANT PART:
if ("Func3" in yourInterface) {
// in this block, yourInterface is coerced to TestInterface2
} else {
// coerced to TestInterface1
}
If (as stated in your question) you have already narrowed the type of the instance to be TestInterface1
, then you'll need to assert that the Func3
property is a function type in order to use it, because the compiler doesn't know it exists.
You can do this using a type predicate, like in the commented example below:
// Because you didn't supply the type of your function,
// I'll provide a template for a generic one here:
type Fn<
Params extends readonly unknown[] = any[],
Result = any,
> = (...params: Params) => Result;
interface TestInterface1 {
Func1: Fn;
Func2: Fn;
}
interface TestInterface2 extends TestInterface1 {
Func3: Fn;
}
function hasFunc3 <T extends TestInterface1>(instance: T): instance is T & Pick<TestInterface2, 'Func3'> {
return typeof (instance as any).Func3 === 'function';
}
// Your question states that the instance is already narrowed to TestInterface1:
declare const instance: TestInterface1;
// Expected error:
instance.Func3(); /*
^^^^^
Property 'Func3' does not exist on type 'TestInterface1'. Did you mean 'Func1'?(2551) */
// Use the type predicate:
if (hasFunc3(instance)) {
instance.Func3(); // ok
}