Hello, world!
I am working with Typescript and Webstorm and I am trying to use a type guard, which does not seem to be totally correct.
This is an example to show what I want to achieve. It is also linked in a playground.
// This is a helper to find the matching class Type
interface correspondsTo<Klass> {}
// An interface for a plain javascript object
interface WizardPojo extends correspondsTo<RealWizard>{
name?: string;
}
// A derivable abstract class
abstract class Action {
performAction() {
console.log('Go!');
}
}
// A class which implements the plain interface and also inherits a method
class RealWizard extends Action implements WizardPojo {
name: string;
performMagic() {
console.log('✨');
}
}
// This is handled by typescript as expected
function lameMagic () {
const harry: RealWizard = new RealWizard();
harry.performMagic(); // correct
harry.performAction(); // correct
const harryPojo: WizardPojo = {};
harryPojo.performMagic() // error: 'performMagic' does not exist -> correct
harryPojo.performAction() // error: 'performAction' does not exist -> correct
}
// Now here is something not working as expected
function realMagic(maybe: WizardPojo | RealWizard ) {
if(isKlassObject(maybe)) {
// Why is that an error?
maybe.performMagic();
maybe.performAction();
const wizard: RealWizard = maybe;
// Why does not the type guard handle the cast?
const asWizard = maybe as RealWizard;
asWizard.performMagic();
asWizard.performAction()
}
}
/*
I guess this type guard needs some more magic to work correctly
The weird thing: Webstorm (without Typescript language service setting set)
recognizes the type correctly
*/
function isKlassObject<Pojo extends correspondsTo<any>> (obj: Pojo)
: obj is Pojo extends correspondsTo<infer Klass> ? Klass : unknown {
return typeof (obj as any).save === 'function';
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
The thing is: When I use Webstorm without the 'Typescript language service' activated, the type guard results in the correct type. However, when I try to convert the code, tsc
throws an error and I don't know why.
In my project I have a lot of those Pojo interfaces and classes which are automatically generated in d.ts
files and I want to use just one generic type guard function to determine if a Pojo is a Klass object. And I want to avoid explicit type cast with as
.
It is important to me to use both, Pojo interfaces and Klass types.
Do you have an idea, how to fix this type guard problem?
CodePudding user response:
I found a solution