我有一個被呼叫的函式updateMany,它接受物體的通用型別,并允許根據物體和“by”屬性更新某些資料,該屬性應該是 keyof data。像這樣的東西:
function updateMany<Table>() {
return <
Data extends { [column in keyof Table]?: Table[column] },
By extends keyof Data
>(params: {
by: By;
data: Table[];
}) => {};
}
(我將該函式包裝在另一個函式中,因為我不確定如何在單個函式中實作它)
現在,一切似乎都在作業,除了data必須擁有所有屬性的事實。當我嘗試里面包裹它Partial,那么我可以傳遞到by不存在中的性能data。我知道我的實作是不正確的,但這是我所能達到的。
在操場上玩
uj5u.com熱心網友回復:
我的建議是這樣寫updateMany():
function updateMany<T>() {
return <
K extends keyof T,
P extends K
>(params: {
by: P;
data: (Pick<T, K> & Partial<T>)[];
}) => { };
}
我的兩個版本,并且你使用柯里要解決缺少“部分型別引數推斷”(的要求,在微軟/打字稿#26242),因為沒有方法來呼叫多個型別引數的功能等T,K以及P與有來電T在讓編譯器推斷K和的同時手動指定P。目前在 TypeScript 中,要么全有要么全無;您可以手動指定所有三個,也可以讓編譯器推斷所有三個。柯里化通過讓一個函式在其中指定T回傳另一個函式來避免這一點,編譯器推斷出K和P。
無論如何,K對應于 的元素上存在的鍵data,并P對應于 中指定的鍵by。我這樣做有兩個型別引數,而不是僅僅K兩個,因為我們不希望編譯器來推斷,K是工會在關鍵的by和的那些data。相反,我們進行約束, P extends K以便K從 推斷出的任何內容data,我們都要求鍵by在該集合中。
從概念上講,我們應該data是有型別的Pick<T, K>[],就是這樣。但既然你說你想一些更好的智能感知自動完成了data,我已經相交 Pick<T, K>有Partial<T>。幸運的是,編譯器似乎僅Pick<T, K>用于推斷條目中K實際存在的那些鍵data,同時還Partial<T>用于為自動完成提供提示。
讓我們看看它是否有效:
const updateManyEntities = updateMany<Entity>();;
const X1 = updateManyEntities({ by: "A", data: [{ A: 1 }] }); // okay
const X2 = updateManyEntities({ by: "A", data: [{ A: 1, B: 2, C: 2 }] }); // okay
const X4 = updateManyEntities({ by: "C", data: [{ A: 1, B: 2 }] }); // error!
// ---------------------------> ~~
// Type '"C"' is not assignable to type '"A" | "B"'
const X3 = updateManyEntities({ by: "D", data: [{ A: 1, B: 2, C: 2 }] }); // error!
// ---------------------------> ~~
// Type '"D"' is not assignable to type '"A" | "B" | "C"'
const X5 = updateManyEntities({ by: "D", data: [{ A: 1, B: 2, C: 3, D: 4 }] }); // error!
// ---------------------------> ~~ ----> ~~~~
// Type '"D"' is not assignable to type 'keyof Entity' |
// Object literal may only specify known properties, and 'D' does not exist in type...
看起來挺好的!
Playground 鏈接到代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/387157.html
上一篇:已解決的承諾型別
