【问题标题】:Is it possible to narrow union type with NonNullable outside of function call?是否可以在函数调用之外使用 NonNullable 缩小联合类型?
【发布时间】:2019-12-10 01:36:01
【问题描述】:

我有这个 useCase 类,我从存储库中获取 Invoice 对象。它的类型是Invoice|null 的联合然后我将这个对象传递给验证函数,它不返回任何东西——如果有什么不对,它就会抛出。我如何描述函数的类型,以便在调用 await verifyEntityVisibilityInCurrentContext(...) 之后,invoice 变量被缩小到仅输入 Invoice?我尝试了本文中提到的 NonNullable 方法,但我很难实现它。 https://blog.logrocket.com/when-to-use-never-and-unknown-in-typescript-5e4d6c5799ad/

代码:

export class GetRelatedDocumentsUseCase {

  private async getInvoiceRelatedDocuments(invoiceId: string, ctx: Context) {
    const invoice: Invoice|null = await this.invoicesRepository.findOneInvoiceById(invoiceId);

    await verifyEntityVisibilityInCurrentContext(invoice, ctx, permissionDeniedMessage, this.companiesRepository);

    //I want here invoice variable to be only of type Invoice
    await doSomethingWithInvoiceObject(invoice)
  }

}


// Helper function - I tried to describe its return type with `never` or apply some code from the article

export async function verifyEntityVisibilityInCurrentContext(
 entity, ctx: Context, permissionDeniedMessage, companiesRepository) :Promise<never | void> {
  if (isNil(entity)) {
    throw new PermissionDenied(permissionDeniedMessage);
  }
  if (!isObjectVisibleInContext(entity, ctx)) {
    const company = await companiesRepository.findCompanyById(entity.companyId);
    const companyUser = company.users.find(companyUser => companyUser.userId === ctx.userId);

    if (isNil(companyUser)) {
      throw new PermissionDenied(permissionDeniedMessage);
    }

    throw new NotFoundInCurrentCompany({
      desiredCompanyId: entity.companyId,
    });
  }
}

【问题讨论】:

  • 你试过await doSomethingWithInvoiceObject(invoice!);吗?
  • 谢谢,我忘记了这个功能。但对我来说,这似乎很老套,不是吗?
  • 请考虑将此代码编辑成minimal reproducible example,其中唯一的问题是您遇到的问题;就目前而言,有很多未定义的类型和值,这会阻止有人将其放入 IDE 并回答您的问题。我建议让您的 verifyEntityVisibility...() 函数返回非空发票对象并让调用函数使用它。您可能需要将该函数设为通用函数,以便返回的对象类型为 Invoice 而不是 any 或现在的任何类型。如果你把它变成minimal reproducible example,我会详细说明。祝你好运!

标签: typescript composition union-types


【解决方案1】:

你已经在你的助手中抛出了错误。你想要做的是在invoicenull 时抛出一个额外的错误。 Typescript 会自动将类型从 Invoice | null 细化到 if ( ! invoice ) 分支下的 Invoice

private async getInvoiceRelatedDocuments(invoiceId: string, ctx: Context): Promise<Invoice> {
    const invoice: Invoice|null = await this.invoicesRepository.findOneInvoiceById(invoiceId);

    await verifyEntityVisibilityInCurrentContext(invoice, ctx, permissionDeniedMessage, this.companiesRepository);

    if ( ! invoice ) {
        throw new Error("null invoice");
    }
    // now variable is only type Invoice
    await doSomethingWithInvoiceObject(invoice);
    return invoice;
}

【讨论】:

    【解决方案2】:

    可以创建类型验证函数

    isInvoice = (arg: Invoice|null): arg is Invoice => {
            return arg !== null ? true : false;
        }
    

    【讨论】:

    • 我知道这种方法,但我不想使用任何if 流命令
    猜你喜欢
    • 2021-08-02
    • 2021-12-14
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    相关资源
    最近更新 更多