[英]Inferring types with a key of a type object in typescript
所以我有一個類型,我想根據傳遞給函數的鍵值動態更新它的字段。 但是,我想做的方式(brokenFunction)給了我一個分配錯誤:類型“34”不能分配給類型“從不”,類型“34”不能分配給類型“從不”。 workingFunction 有效,但不是那么方便。 有沒有人有辦法使這項工作? 我猜它涉及泛型,但我仍然不明白為什么類型保護不起作用.....
interface Todo {
id: number;
text: string;
}
const todo = {
id: 1,
text: "Buy milk",
};
function brokenFunction(x: Todo, field: keyof Todo): void {
if (typeof field === 'number') {
x[field] = 34
} else if (typeof field === 'string') {
x[field] = 'something else'
}
}
function workingFunction(x: Todo, field: keyof Todo): void {
if (field == 'id') {
x[field] = 2345
} else if (field == 'text') {
x[field] = 'asdfsf'
}
}
游樂場鏈接
在brokenFunction()
, field
參數的類型是"id" | "text"
"id" | "text"
,表示它是字符串"id"
或字符串"text"
。 在這兩種情況下,在運行時, typeof field
都是"string"
。 因此永遠不會到達第一個if
塊,而將始終到達第二個:
if (typeof field === 'number') {
x[field] = 34; // can never happen
} else if (typeof field === 'string') {
x[field] = 'something else'; // might be an error
}
我想你可能是指這樣的事情,這也不起作用:
function brokenFunction2(x: Todo, field: keyof Todo): void {
if (typeof x[field] === 'number') {
x[field] = 34; // error!
} else if (typeof x[field] === 'string') {
x[field] = 'something else'; // error!
}
}
那是因為編譯器不會執行您試圖達到的那種控制流分析; 您希望編譯器根據typeof x[field]
縮小field
類型,但事實並非如此。 這與一個已知問題 microsoft/TypeScript#10530 相關,其中對屬性的此類括號訪問不會觸發控制流分析縮小。 那好吧。
那么,我們該如何解決呢? 一種可能的方法是創建一個用戶定義的類型保護函數,它明確地告訴編譯器你在尋找什么:
function fieldGuard<T, V>(
x: T,
k: keyof T,
guard: (x: any) => x is V
): k is { [K in keyof T]-?: T[K] extends V ? K : never }[keyof T] {
return guard(x[k]);
}
函數fieldGuard()
接受一個對象x
、該對象k
一個鍵,以及一個你想要檢查屬性x[k]
的保護函數。 然后根據保護的結果縮小密鑰k
的類型。 然后這有效:
function okayFunction(x: Todo, field: keyof Todo): void {
if (fieldGuard(x, field, (y): y is number => typeof y === 'number')) {
x[field] = 34;
} else if (fieldGuard(x, field, (y): y is string => typeof y === 'string')) {
x[field] = "something else";
}
}
這有點乏味,但它非常接近您的原始邏輯,並且編譯器願意至少為您做一些檢查。 如果沒有對 microsoft/TypeScript#10530 的修復,我想不出比上面更好的方法,或者只是像在您的workingFunction()
檢查鍵本身。
好的,希望有幫助; 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.