sam*_*mvv 34 types circular-reference typescript
我有以下代码:
type Document = number | string | Array<Document>;
Run Code Online (Sandbox Code Playgroud)
TypeScript抱怨以下错误:
test.ts(7,6): error TS2456: Type alias 'Document' circularly references itself.
Run Code Online (Sandbox Code Playgroud)
显然不允许循环引用.但是,我仍然需要这种结构.这将是一个解决方法?
Kri*_*amp 31
TypeScript的创建者解释了如何在这里创建递归类型:https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
循环引用的解决方法是使用extends Array.在您的情况下,这将导致此解决方案:
type Document = number | string | DocumentArray;
interface DocumentArray extends Array<Document> { }
Run Code Online (Sandbox Code Playgroud)
Dan*_*ber 17
我们已经有了很好的答案,但我认为我们可以从一开始就接近你想要的东西:
你可以尝试这样的事情:
interface Document {
[index: number]: number | string | Document;
}
// compiles
const doc1: Document = [1, "one", [2, "two", [3, "three"]]];
// fails with "Index signatures are incompatible" which probably is what you want
const doc2: Document = [1, "one", [2, "two", { "three": 3 }]];
Run Code Online (Sandbox Code Playgroud)
与NPE的答案相比,您不需要围绕字符串和数字的包装器对象.
如果您希望单个数字或字符串成为有效文档(这不是您提出的问题,但NPE的答案意味着什么),您可以尝试这样做:
type ScalarDocument = number | string;
interface DocumentArray {
[index: number]: ScalarDocument | DocumentArray;
}
type Document = ScalarDocument | DocumentArray;
const doc1: Document = 1;
const doc2: Document = "one";
const doc3: Document = [ doc1, doc2 ];
Run Code Online (Sandbox Code Playgroud)
更新:
使用具有索引签名而不是数组的接口具有丢失类型信息的缺点.Typescript不允许您调用find,map或forEach等数组方法.例:
type ScalarDocument = number | string;
interface DocumentArray {
[index: number]: ScalarDocument | DocumentArray;
}
type Document = ScalarDocument | DocumentArray;
const doc1: Document = 1;
const doc2: Document = "one";
const doc3: Document = [ doc1, doc2 ];
const doc = Math.random() < 0.5 ? doc1 : (Math.random() < 0.5 ? doc2 : doc3);
if (typeof doc === "number") {
doc - 1;
} else if (typeof doc === "string") {
doc.toUpperCase();
} else {
// fails with "Property 'map' does not exist on type 'DocumentArray'"
doc.map(d => d);
}
Run Code Online (Sandbox Code Playgroud)
这可以通过更改DocumentArray的定义来解决:
interface DocumentArray extends Array<ScalarDocument | DocumentArray> {}
Run Code Online (Sandbox Code Playgroud)
NPE*_*NPE 13
这是一种方法:
class Doc {
val: number | string | Doc[];
}
let doc1: Doc = { val: 42 };
let doc2: Doc = { val: "the answer" };
let doc3: Doc = { val: [doc1, doc2] };
Run Code Online (Sandbox Code Playgroud)
引用自身的类型称为"递归类型",将在语言规范的第3.11.8节中讨论.以下摘录解释了为什么您的尝试无法编译:
类和接口可以在其内部结构中引用自身......
您的原始示例既不使用类也不使用接口; 它使用类型别名.
Her*_*ine 11
从 Typescript 4 开始,循环类型对于很多事情来说都是固定的,但对于 Record 来说却不是(这是设计使然的)。如果您遇到此问题,可以按照以下方法进行操作。
// This will fire a TS2456 error: Type alias "Tree" circularly reference itself
type Tree = Record<string, Tree | string>;
Run Code Online (Sandbox Code Playgroud)
// No error
type Tree = {
[key: string]: Tree | string;
};
Run Code Online (Sandbox Code Playgroud)
参考:https ://github.com/microsoft/TypeScript/pull/33050#issuecomment-543365074
| 归档时间: |
|
| 查看次数: |
10302 次 |
| 最近记录: |