我試圖通過僅過濾一個屬性來創建一個通用函式來轉換物件 - 沿著以下幾行:
function pickOnePropertyUntyped(data: any, key: any): any {
return {
[key]: data[key]
}
}
因此,期望的行為是:
const a: A = {
a: 'a',
b: 1
}
const r = pickOnePropertyUntyped(a, 'a'); // {'a': 'a'}
我在獲取所需型別和實作方面遇到問題。
我的嘗試是:
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type NoUnion<Key> =
[Key] extends [UnionToIntersection<Key>] ? Key : never;
type PickOneProperty<T, P extends keyof T & string> = {
[K in keyof T as K extends NoUnion<P> ? K : never]: T[K]
}
function pickOneProperty<T, K extends keyof T & string>(
data: T,
key: K,
): PickOneProperty<T, K> {
return {
[key]: data[key]
}
}
哪個:
- 正確地將輸入屬性限制為只有一個鍵(我使用了有沒有辦法防止 TypeScript 中的聯合型別?)
- 正確推斷輸出型別
不幸的是,它將回傳型別標記為不正確。
操場
uj5u.com熱心網友回復:
您在這里觀察到的或多或少是 TypeScript 中缺少的功能。大多數情況下,當您嘗試使用計算屬性鍵時,TypeScript 會自動將索引簽名添加到物件的型別。只有一些例外;例如,當鍵的型別已經是已知的字串文字型別時(如此處所示)。在此處查看有關此問題的討論。
索引簽名打破了這里的打字。據我所知,這個問題沒有“令人滿意”的解決方案。即使是普通的型別斷言在這里也不起作用,因為 TypeScript 認為這兩種型別之間沒有重疊。你可以做的是先斷言unkown
,然后再斷言PickOneProperty<T, K>
function pickOneProperty<T, K extends keyof T & string>(
data: T,
key: K,
): PickOneProperty<T, K> {
return {
[key]: data[key]
} as unknown as PickOneProperty<T, K>
}
請注意,現在這個實作中幾乎沒有型別安全。
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/527573.html
標籤:打字稿