【问题标题】:How to correctly do recursive type definition in TypeScript?如何在 TypeScript 中正确进行递归类型定义?
【发布时间】:2018-12-04 18:50:21
【问题描述】:

我有一个由嵌套数组和对象组成的任意结构,其中 ValidationError 对象作为叶子。要输入这个,我需要一个递归类型,如 Typescript guidelines 所示。

虽然赋值 (const x = ...) 似乎通过了类型检查,但访问结构 (x.errors.a) 会出现我无法理解的 TypeScript 错误:

错误:TS2339:“ValidationResultElement”类型上不存在属性“a”。

类型“ValidationResultObject”上不存在属性“a”。

see code on TypeScript Playground

export interface ValidationResult {
  errors: ValidationResultElement;
}

type ValidationResultElement =
  ValidationResultObject | ValidationResultArray | ValidationError;

interface ValidationResultArray extends Array<ValidationResultElement> {
}

interface ValidationResultObject {
  [key: string]: ValidationResultElement;
}

interface ValidationError {
  details: string;
}

// This works:
const x: ValidationResult = {
    errors: { a: { b: [{ c: { details: 'foo' } }] } }
};

// This produces a type error:
console.log(x.errors.a);

【问题讨论】:

  • 问题是你可能必须告诉 TypeScript 联合中的三个 ResultElement 中的哪一个要考虑(x.errors as ValidationResultObject).a

标签: typescript recursion types


【解决方案1】:

您需要缩小类型。这是一个例子,但我有一些警告!

function isValidationResultObject(obj: any): obj is ValidationResultObject {
  return (obj && (!obj.type) && (!obj.length));
}

if (isValidationResultObject(x.errors)) {
  console.log(x.errors.a);
}

我已经拼凑了一个自定义类型保护来消除其他类型,但这可能是错误的,它只是展示了这个概念。您需要编写一个有效的类型保护。

您可能会发现区分联合类型使深入研究许多属性变得更容易。

您可以通过断言强制类型缩小,但类型保护更诚实,并确保您真正处理的是您期望的类型。

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 2012-10-02
    • 2018-05-30
    • 2020-10-18
    • 2017-12-21
    • 2017-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多