如何告诉 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
考虑这段代码:
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