简体   繁体   English

如何在 TypeScript 中正确地进行递归类型定义?

[英]How to correctly do recursive type definition in TypeScript?

I have an arbitrary structure consisting of nested arrays and objects, with ValidationError objects as leaves.我有一个由嵌套数组和对象组成的任意结构,其中 ValidationError 对象作为叶子。 To type this I need a recursive type as shown in Typescript guidelines .要键入此内容,我需要一个递归类型,如Typescript 指南中所示。

While the assignment ( const x = ... ) seems to pass the type check, accessing the structure ( x.errors.a ) gives a TypeScript error which I cannot understand:虽然赋值( const x = ... )似乎通过了类型检查,但访问结构( x.errors.a )会产生一个我无法理解的 TypeScript 错误:

Error: TS2339: Property 'a' does not exist on type 'ValidationResultElement'.错误:TS2339:类型“ValidationResultElement”上不存在属性“a”。

Property 'a' does not exist on type 'ValidationResultObject'.类型“ValidationResultObject”上不存在属性“a”。

see code on TypeScript Playground 在 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);

You need to narrow the type.您需要缩小类型。 This is an example but I have caveats!这是一个例子,但我有警告!

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

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

I have chucked together a custom type guard to eliminate the other types, but it is probably wrong, it just demonstrates the concept.我已经将自定义类型保护放在一起以消除其他类型,但这可能是错误的,它只是演示了这个概念。 You need to write a type guard that works.您需要编写一个有效的类型保护。

You may find a discriminated union type makes this easier that delving into lots of properties.您可能会发现有区别的联合类型使深入研究许多属性更容易。

You could force the type to narrow with an assertion, but a type guard is more honest and ensures you are really dealing with the type you expect.您可以通过断言强制类型缩小,但类型保护更诚实并确保您真正处理您期望的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM