如何告诉 TypeScript 我知道一个方法存在?

How to tell TypeScript that I know a method exists?

考虑这段代码:

export default class OptimizelyFeatureFlags implements FeatureFlags {
    private body: string;

    constructor(
        protected callEndpoint: CacheableEntity,
        protected baseUrl: string,
        protected envName: string,
        protected featureId: string
    ) {}

    /**
     * Calls the Optimizely endpoint to get the info
     */
    public async fetch(): Promise<void> {

        // Determine if this is a CallEndpoint (or child thereof)
        if (this.callEndpoint['hasAuthorisationToken'] != undefined) {
            if (!this.callEndpoint.hasAuthorisationToken()) {
                throw Error(
                    'This endpoint requires an auth token to work'
                );
            }
        }

        this.body = await this.callEndpoint.getResource(this.baseUrl + `/v2/features/${this.featureId}`);
    }

   ...

}

现在CacheableEntity是一个接口,只需要getResource()就可以匹配合约。方法 hasAuthorisationToken 未在其中定义。

现在,如果 class 有一个 hasAuthorisationToken() 方法,我知道它是一个 CallEndpoint,它将实现 CacheableEntity。这是一个类型测试——根据我的研究,我了解到 TypeScript 不提供 运行 时间类型测试,因为在 运行 时间它只是 JavaScript.

但是,这不会编译。在 Jest 测试中,我得到:

  ● Test suite failed to run

    src/service/feature-flags/OptimizelyFeatureFlags.ts:31:36 - error TS2339: Property 'hasAuthorisationToken' does not exist on type 'CacheableEntity'.

    31             if (!this.callEndpoint.hasAuthorisationToken()) {
                                          ~~~~~~~~~~~~~~~~~~~~~

我想有几种方法可以解决这个问题 - 也许我可以将对象从 CacheableEntity 转换为 CallEndpoint?我想告诉转译器我知道我在做什么。

或者我可以这样做:

if (this.callEndpoint['hasAuthorisationToken'] != undefined) {
    const hasAuth = this.callEndpoint['hasAuthorisationToken']();
    ...
}

不过,我想知道这样是不是有点乱。最好的解决方法是什么?

是的,你的第一个选择是最好的。最具可读性。

if (this.callEndpoint['hasAuthorisationToken'] != undefined) {
    const callEndpoint = this.callEndpoint as CallEndpoint;
    const hasAuth = callEndpoint.hasAuthorisationToken();
    ...
}

不确定 != undefined 位。你可以做 this.callEndpoint instanceof CallEndpoint 吗?不确定你是如何实例化这些东西的,但如果你可以使用 instanceof,打字稿将接受对 this.callEndpoint 上的方法的调用,而无需强制转换。像这样:

if (this.callEndpoint instanceof CallEndpoint) {
    const hasAuth = this.callEndpoint.hasAuthorisationToken();
    ...
}

您可以使用用户定义的类型保护:https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards