![](/img/trans.png)
[英]How to specify a type in Typescript which represents the union of 2 functions
[英]Typescript: How to declare a Type which represents a Treeview? Is it possible?
Typescript是JavaScript的TYPED超集,可以編譯為JavaScript,很好! 它可以幫助我們減少一些錯別字等,確定! 我想創建一個在方法中用作參數的接口。 該接口必須表示將用於解析對象的樹視圖。
示例: w1[a2].x[b02].yz
是訪問myObject
中z
值的路徑
const path = "w1[a2].x[b02].yz"; const treeOfIdentifiers = { "w1": { key: "idLvlW", "x": { key: "idLvlX" } } } const myObject = { w0: "Hello Root", w1: [{ idLvlW: "a1", x: [{ idLvlX: "b01", y: { z: "hello world from w1[a1].x[b01].yz" } }, { idLvlX: "b02", y: { z: "hello world from w1[a1].x[b02].yz" } }, { idLvlX: "b03", y: { z: "hello world from w1[a1].x[b03].yz" } }, { idLvlX: "b04", y: { z: "hello world from w1[a1].x[b04].yz" } } ] }, { idLvlW: "a2", x: [{ idLvlX: "b01", y: { z: "hello world from w1[a2].x[b01].yz" } }, { idLvlX: "b02", y: { z: "hello world from w1[a2].x[b02].yz" } }, { idLvlX: "b03", y: { z: "hello world from w1[a2].x[b03].yz" } }, { idLvlX: "b04", y: { z: "hello world from w1[a2].x[b04].yz" } } ] }, { idLvlW: "a3", x: [{ idLvlX: "b01", y: { z: "hello world from w1[a3].x[b01].yz" } }, { idLvlX: "b02", y: { z: "hello world from w1[a3].x[b02].yz" } }, { idLvlX: "b03", y: { z: "hello world from w1[a3].x[b03].yz" } }, { idLvlX: "b04", y: { z: "hello world from w1[a3].x[b04].yz" } } ] } ]
接口|什么是類型treeOfIdentifiers
(如果沒有any
如果使用打字稿我的代碼!)? 這樣做的目的是確保將提供 treeOfIdentifiers的每個節點, 屬性key
,並且我們不知道treeOfIdentifiers
的結構,因為我們不知道要解析的對象的結構!
這在TypeScript中很難表達。 例如,將名稱為key
的字符串值屬性添加到非string
值的字典中並不是很容易強類型化的操作……這可能意味着您可能希望使類型更簡單(例如,每個節點都具有key
屬性和dictionary
屬性)。
我什至沒有想到要在使用treeOfIdentifiers
遍歷myObject
時確保其有效,因為您沒有對此提出treeOfIdentifiers
,而這已經非常復雜了。
type NonRootOfTreeOfIdentifiers<T> = { [K in 'key' | keyof T]:
K extends 'key' ? string :
K extends keyof T ? NonRootOfTreeOfIdentifiers<T[K]> : never
};
type TreeOfIdentifiers<T> = { [K in keyof T]: NonRootOfTreeOfIdentifiers<T[K]> };
const asTreeOfIdentifiers = <T extends TreeOfIdentifiers<T>>(t: T): T => t;
最棘手的部分在NonRootOfTreeOfIdentifiers<T>
。 它采用類型T
表示有效的treeOfIdentifiers
的非根節點。 它將一個key
屬性添加到T
,然后將T
這些屬性映射到一個新類型: key
被映射為一個string
屬性,而所有其他屬性都映射到其自身的NonRootOfTreeOfIdentifiers<>
版本。 所以NonRootOfTreeOfIdentifiers<T>
通過水平走下T
並將其轉換為另一種類型。 如果T
是有效的非根節點,則NonRootOfTreeOfIdentifiers<T>
將是有效的非根節點。
TreeOfIdentifiers
類型的函數表示根節點,該節點不需要key
屬性,但否則會遍歷到NonRootOfTreeOfIdentifiers
。
最后, asTreeOfIdentifiers
函數接受類型為T
的參數,該參數必須與TreeOfIdentifiers<T>
兼容,然后返回該參數。 這意味着,它將僅接受符合規則的對象。 因此,它驗證了其論點,但沒有改變。
讓我們看看它是否有效:
const treeOfIdentifiers = asTreeOfIdentifiers({
"w1": {
key: "idLvlW",
"x": {
key: "idLvlX"
}
}
});
編譯后, treeOfIdentifiers
推斷為類型
{
"w1": {
key: string;
"x": {
key: string;
};
};
}
如果您以某種方式搞砸了,則會收到錯誤消息:
const missingKey = asTreeOfIdentifiers({
"w1": {
key: "idLvlW",
"x": {
kee: "idLvlX" // oops
}
}
});
// error: Property 'key' is missing in type '{ kee: string; }'
要么
const extraProperty = asTreeOfIdentifiers({
"w1": {
key: "idLvlW",
x: {
key: "idLvlX"
}
y: 123 // oops
}
});
// error: Types of property 'y' are incompatible.
// Type 'number' is not assignable to type 'NonRootOfTreeOfIdentifiers<number>'.
這樣一切都可以正常進行。 不過,我不確定這是否值得。 如果您嘗試捕獲諸如"idLvlX"
類的文字字符串值類型(而不只是string
),它會變得更加毛茸茸。 而且,正如我所說,我什至沒有考慮過如何針對類型系統中的treeOfIdentifiers
驗證myObject
。
無論如何,祝你好運。 希望能有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.