我有以下型別:
type OrBranch = {
or: Branch[]
}
type AndBranch = {
and: Branch[]
}
我想要一個Branch可以是 anOrBranch或 an的型別AndBranch。所以我首先嘗試:
type Branch = AndBrand | OrBranch
作業得很好,除非我想做類似的事情:
let branch: Branch = ...
let andOr = 'and'; // or 'or'
let nodes = branch[andOr]
然后我知道那branch是不可索引的。好的,所以我嘗試了一種可索引型別:
type AndOr = 'and' | 'or';
type Branch = Record<AndOr, Branch[]>;
但這需要兩者and都or存在,所以在這種情況下我不能將 AndBranch 轉換為 Branch。
相似地
type Branch = Record<AndOr, Branch[]> | AndBranch | OrBranch
不起作用,出于同樣的原因。
雖然我可以使用型別保護來確定型別,但我有對這些物件進行操作的長函式,其中除了屬性之外,它們可以被視為相同。我希望通過使用變數來消除一堆重復的代碼andOr,而型別保護并沒有真正阻止。例如:
let retval = {} as Branch;
if (isAnd(branch)) { // branch is a Branch parameter passed in
(retval as AndBranch).and = [] as Branch[];
set = (retval as AndBranch).and;
} else {
(retval as OrBranch).or = [] as Branch[];
set = (retval as OrBranch).or;
}
set = _.reduce(set, (all, item: Branch)=> {
if (isAnd(branch) && isAnd(item))
return _.union(all, item.and);
else if (isOr(branch) && isOr(item))
return _.union(all, item.or);
else
return all;
}, [] as Branch[]);
對比
andOr = isAnd(branch) ? 'and' : 'or';
let retval = {} as Branch;
retval[andOr] = _.reduce(set, (all, item: Branch) => {
if (item[andOr])
return _.union(all, item[andOr]);
else
return all;
}, [] as Branch[]);
我知道有一種方法可以只要求一個andand or(就像Enforce Typescript object 的答案只有一個 key from a set)。但該型別不可索引。
是否可以同時獲得這兩種效果?
uj5u.com熱心網友回復:
使型別可索引并不能解決基本問題,即您試圖在and可能是and分支(因此具有該屬性)或可能是or分支(因此不是)的東西上使用該屬性。相反,詢問分支它有什么并使用它,因為這允許 TypeScript 縮小型別:
if ("and" in branch) {
// ...use `branch.and`...
} else {
// ...use `branch.or`...
}
andOr如果您的代碼認為它知道分支是什么,則可以將其與您的代碼結合起來,也許可以使用型別斷言函式:
function assertIsAndBranch(branch: Branch): asserts branch is AndBranch {
if (!("and" in branch)) {
throw new Error(`branch is not an AndBranch`);
}
}
// (And `assertIsOrBranch`)
然后:
if (andOr === "and") {
assertIsAndBranch(branch);
// ...here, TypeScript knows `branch` is an `AndBranch`...
}
重新編輯:如果您有重要的代碼需要處理AndBranch'sand或OrBranch's包含的專案or而不知道或關心它們是AndBranch或OrBranch實體,我會將它們重新設計為一個有區別的工會,工會的所有成員都有相同items(或其他)屬性:
type OrBranch = {
type: "or";
items: Branch[];
};
type AndBranch = {
type: "and";
items: Branch[];
};
這樣,不關心它是什么型別的分支的代碼可以使用items. 您顯示的代碼是:
const items = _.reduce(branch.items, (all, item) => {
return _.union(all, item.items);
}, [] as Branch[]);
const retval = {type: branch.type, items};
游樂場鏈接
讓屬性具有雙重職責(既指示分支的型別和其中的專案),就像它們在當前型別中所做的那樣,使得撰寫型別安全的代碼來處理專案而不知道/關心什么型別的分支真的很困難。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/428136.html
標籤:javascript 打字稿 类型
