简体   繁体   English

为什么 TypeScript 递归类型别名失败 generics

[英]Why does TypeScript recursive type alias fail with generics

I've got two type definitions describing almost the same thing:我有两个描述几乎相同事物的类型定义:

 // compilation fails with `Type alias 'StringOrRecordOfStrings' circularly references itself.ts(2456)`
type StringOrRecordOfStrings = string | string[] | Record<string, StringOrRecordOfStrings>;

 // compiles without problems
type StringOrRecordOfStrings = string | string[] | { [property: string]: StringOrRecordOfStrings };

Is anyone able to explain why the first type definition doesn't compile?有谁能解释为什么第一个类型定义不能编译?

The reason why Record<string, StringOrRecordOfStrings> is not allowed is that Record is a generic type , rather than a class or an interface.不允许Record<string, StringOrRecordOfStrings>的原因是Record是泛型类型,而不是 class 或接口。

There isn't a lot of clear documentation on this, but recursive type references for properties in objects, index signatures, and mapped types have been around for quite a while.没有很多关于此的明确文档,但是对象中的属性、索引签名和映射类型的递归类型引用已经存在了很长一段时间。 The following works as early as TypeScript 3.3:以下作品早于TypeScript 3.3:

type Recursive = {p: Recursive} | {[p: string]: Recursive} | {[Key in 'a']: Recursive}

TypeScript 3.3 playground TypeScript 3.3游乐场

This is why your second example type (with an index signature) checks.这就是您的第二个示例类型(带有索引签名)检查的原因。

TypeScript 3.7 extended the support for recursive references, as explained in this PR : TypeScript 3.7 扩展了对递归引用的支持,如本PR中所述:

  • Instantiations of generic class and interface types (for example Array<Foo> ).泛型 class 和接口类型(例如Array<Foo> )的实例化。
  • Array types (for example Foo[] ).数组类型(例如Foo[] )。
  • Tuple types (for example [string, Foo?] ).元组类型(例如[string, Foo?] )。

So now, also these three examples are valid:所以现在,这三个例子也是有效的:

type RecursiveCI = Promise<RecursiveCI>
type RecursiveT = [number, boolean, RecursiveT]
type RecursiveA = RecursiveA[]

I assume the sample is just test code, but you can get it to type check by using a helper interface like this:我假设该示例只是测试代码,但您可以使用这样的帮助程序接口对其进行类型检查:

type StringOrRecordOfStrings = string | string[] | Record<string, RecordInterface>

interface RecordInterface extends Record<string, StringOrRecordOfStrings> {}

TypeScript playground TypeScript 操场

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

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