我有一個查詢元素陣列,其中每個元素可以是一個術語或子查詢,其中包含以“AND”或“OR”開頭,后跟合法查詢元素、術語或嵌套子查詢等的陣列。
例如,這些都應該是合法的輸入:
const query1 = "Hello"
const query2 = ["AND", "Hello", "World"]
const query3 = ["OR", ["AND", "Hello", "World"], ["AND", "Hola", "Mundo"]]
Variadric元組在TS 4.0應允許您型別的陣列的第一個元素和另一種型別的用于其余:
type IQuery = ["AND" | "OR", ...Array<string>]
const query = ["AND", "Hello", "World"] // valid
遞回型別的TS 3.7應允許您定義使用本身就是一種型別:
type IQueryOps = string | Array<IQueryOps>
const query: IQueryOps = ["Hello", "World", ["Hola", "Mundo"]] // valid
但是當圓形型別展開時,我似乎無法將兩者結合起來。在這種情況下,每個查詢都以一個運算子開始,然后是一個字串或另一個像這樣的有效查詢:
type IOperator = "AND" | "OR"
type IQuery = [IOperator, ...Array<string | IQuery>]
在這種情況下,我收到錯誤:
型別別名“IQuery”回圈參考自身。(2456)
無論如何,即使有變通方法,是否也可以輸入此內容,或者我是否必須將其展開到我希望從型別角度支持的所需深度級別?
TS Playground 中的演示
進一步閱讀
- 為陣列定義一個型別,其中第一個元素比其余元素更具體
- 如何在 TypeScript 中創建回圈參考型別?
uj5u.com熱心網友回復:
我認為這可能是microsoft/TypeScript#41164 中報告的 TypeScript 設計限制的一個實體。正如那里提到的,
某些圓形是允許的 [...] 但其他圓形不是,例如
type Identity<T> = T; type T3 = Identity<T3>;泛型實體被推遲,所以在點TS分析[A]宣告,它不能告訴我們,如果它在
Record的情況下(將被允許)或Identity情況(將不會被允許)。只有在流程的后期,我們才能判斷這實際上是可以的,但如果不可以,那么回去開始抱怨就“太晚了”。
如果這是問題所在,那么雖然以下內容應該“沒問題”,但編譯器似乎無法及早告知以允許它:
// type IQuery = string | ["AND" | "OR", ...Array<IQuery>] error
(我稍微更改了您的定義以允許該const query1 = "Hello"行)。
幸運的是,Array<T>有一個替代的內置語法T[],它似乎不會以這種方式推遲:
type IQuery = string | ["AND" | "OR", ...IQuery[]] // okay
這有效:
const query1: IQuery = "Hello"
const query2: IQuery = ["AND", "Hello", "World"]
const query3: IQuery = ["OR", ["AND", "Hello", "World"], ["AND", "Hola", "Mundo"]]
const query4: IQuery = ["AND", ["OR", ["AND"]]];
const badQuery1: IQuery = 3; // error
// Type 'number' is not assignable to type 'IQuery'
const badQuery2: IQuery = ["AND", "Hello", 123]; // error
// Type 'number' is not assignable to type 'IQuery'
const badQuery3: IQuery =
["OR", query1, query2, "then", query3, query4, "if", []]; // error
// Type '[]' is not assignable to type 'IQuery'.
Playground 鏈接到代碼
uj5u.com熱心網友回復:
查看Recursive Types的描述,不明確支持可變引數元組。我不知道它是否算作下面列出的三種型別之一:
此 PR 所做的具體更改是允許型別引數在以下型別的別名型別中進行回圈參考:
- 泛型類和介面型別的實體化(例如
Array<Foo>)。- 陣列型別(例如
Foo[])。- 元組型別(例如
[string, Foo?])。
我通過...從您的代碼中洗掉可變引數運算子來測驗這個理論:
type IOperator = "AND" | "OR"
type IQuery = [IOperator, Array<string | IQuery>] // NO ERROR
該更改沒有導致錯誤,但它不支持您想要的語法。
所以我重新撰寫(并簡化)了您的代碼如下,并且它有效!我的理論是不支持將可變引數運算子與泛型類實體化結合使用,無論是有意還是我不知道的錯誤。
type IOperator = "AND" | "OR"
type IQuery = string | [IOperator, ...IQuery[]]
// examples from your question
const query1: IQuery = "Hello"
const query2: IQuery = ["AND", "Hello", "World"]
const query3: IQuery = ["OR", ["AND", "Hello", "World"], ["AND", "Hola", "Mundo"]]
// deep nesting
const query4: IQuery = ["OR", ["AND", "Hello", ["AND", "Beautiful", "World"]], ["AND", "Hola", "Mundo"]]
//errors
const query5: IQuery = ["OR", ["NOR", "Hello", ["AND", "Beautiful", "World"]], ["AND", "Hola", "Mundo"]]
const query6: IQuery = ["OR", ["AND", 42, ["AND", "Beautiful", "World"]], ["AND", "Hola", "Mundo"]]
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/344886.html
