Reputation: 654
I have a class which has a private, optional property (private foo?: Foo
). Within the private code of the class, I need to be able to validate that this property exists, so that I can handle failure once at the beginning of the method and then deal with it as non-optional in the rest of the block.
The code below works like a charm if foo
is public. However, since I need foo to be private, it doesn't work. Instead of validating this
as conforming to FooBar & FooContainer
, the type of this
becomes never
.
This behavior totally makes sense for public usage where I don't want to allow external code to validate the existence of a private property. However, I am trying to find a type-predicate-like solution I can use privately within my class to make the property in question non-optional.
interface Foo {
bar: string;
}
interface FooContainer {
foo: Foo;
}
class FooBar {
private foo?: Foo;
bar?: string
constructor(foo?: Foo, bar?: string) {
this.foo = foo;
this.bar = bar;
}
private isFooContainer(): this is FooContainer {
const { foo } = this;
return typeof foo !== "undefined";
}
printFoo() {
if (!this.isFooContainer()) throw new Error("There is no foo!!!!");
// For the rest of this method `this.foo` should be typed as `Foo` rather than `Foo | undefined`
console.log(this.foo.bar); // <--- No optional chaining (`this.foo?.bar`) required here.`
}
}
Upvotes: 2
Views: 532
Reputation: 3321
Is it as simple as inlining the check itself? I wonder if I've missed the purpose of having an interface and a predicate but this seems fine to me...
interface Foo {
bar: string;
}
class FooBar {
#foo?:Foo;
bar?:string;
constructor(foo?:Foo, bar?:string) {
this.#foo = foo;
this.bar = bar;
}
printFoo() {
if(typeof this.#foo === "undefined") throw new Error("There is no foo!!!!");
console.log(this.#foo.bar);
}
}
Upvotes: 1