当返回类型成员具有联合类型时,强制确定成员从方法返回类型



采用以下方法:

private async getJobExecutionIds(): Promise<Athena.ListQueryExecutionsOutput> {
const params = { NextToken: this.nextToken, MaxResults: 50 };
const response = await this.athena.listQueryExecutions(params).promise();
if (response.QueryExecutionIds instanceof Array) {
return response;
}
throw new Error("No Athena QueryExecutionIds");
}

我添加了response.QueryExecutionIds instanceof Array检查,以保证我的用户安全地依赖于QueryExecutionIds: string[] | undefined的存在

但是,当我使用此方法时:

const executionIds = await this.getJobExecutionIds();

我仍然不能依靠executionIds.QueryExecutionIds作为string[]在那里。

我怎样才能以干净的方式实现这一目标?

这里的问题是,虽然打字稿具有类型保护,但它不能推理类型中的属性,只能推理类型。你需要稍微"帮助"打字稿,才能理解如果response.QueryExecutionIds instanceof Array,它实际上是一种全新的类型。

因此,第一步是基于原始类型定义此新类型。在此类型中,QueryExecutionIds不能未定义。这里有两个选项,选择你最喜欢的:

type ListQueryExecutionsOutputSafe = Athena.ListQueryExecutionsOutput & {QueryExecutionIds: string[]}
interface ListQueryExecutionsOutputSafe extends Athena.ListQueryExecutionsOutput {
QueryExecutionIds: string[];
}

下一步是定义一些自定义类型保护:

const checkIfListQueryExecutionsOutputIsSafe = (obj: Athena.ListQueryExecutionsOutput): obj is ListQueryExecutionsOutputSafe => 
!!obj.QueryExecutionIds; 

最后:

private async getJobExecutionIds(): Promise<ListQueryExecutionsOutputSafe> {
const params = {NextToken: this.nextToken, MaxResults: 50};
const response = await this.athena.listQueryExecutions(params).promise();
if (checkIfListQueryExecutionsOutputIsSafe(response)) {
return response;
}
throw new Error("No Athena QueryExecutionIds");
}

但为什么要止步于此呢?让我们让一切都变得通用:

type TypeWithNotNullProp<T, SafeKey extends keyof T> = T & {[K in SafeKey]-?: T[K]}
const checkSafeProp = <T, SafeKey extends keyof T>(obj: T, key: SafeKey): obj is TypeWithNotNullProp<T, SafeKey> => 
!!obj[key];

private async getJobExecutionIds(): Promise<ListQueryExecutionsOutputSafe> {
const params = {NextToken: this.nextToken, MaxResults: 50};
const response = await this.athena.listQueryExecutions(params).promise();
if (checkSafeProp(response, 'QueryExecutionIds')) {
return response;
}
throw new Error("No Athena QueryExecutionIds");
}

我通常把TypeWithNotNullPropcheckSafeProp放在一些实用程序文件中,处理不同的 API 非常方便。

最新更新