在私有属性上使用 TypeScript 类型谓词

问题描述

我有一个具有私有可选属性 (private foo?: Foo) 的类。在类的私有代码中,我需要能够验证此属性是否存在,以便我可以在方法开始时处理一次失败,然后在块的其余部分将其作为非可选处理。

下面的代码就像一个魅力如果 foo 是公开的。但是,因为我需要 foo 是私有的,所以它不起作用。与验证 this 是否符合 FooBar & FooContainer 不同,this 的类型变为 never

这种行为对于公共使用完全有意义,因为我不想让外部代码验证私有属性的存在。但是,我正在尝试找到一种类似类型谓词的解决方案,我可以在我的班级中私下使用,以使相关属性成为非可选属性

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.`
    }
}

解决方法

是否像内联检查本身一样简单?我想知道我是否错过了拥有接口和谓词的目的,但这对我来说似乎很好......

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); 
    }
}

Typescript Playground