我有一個函式可以像這樣更新物件的欄位:
const obj = {a: 1, b:2};
const changeObj = (field, value) => obj[field] = value;
這顯然是簡化的,但我試圖根據傳入的欄位屬性正確輸入。這與我得到的一樣接近:
interface ITest {
name: string;
anotherProp: number;
lastProp: IOtherInterface;
}
const obj: ITest = {name: 'test', anotherProp: 1, lastProp: {a: 'b'}};
const changeObj = (field: keyof ITest, val: ITest[keyof ITest]) => obj[field] = val;
這讓我大部分時間都在那里,但從技術上講,它val可以具有字串、數字或 IOtherInterface 的值型別。有沒有辦法告訴函式如果我傳入name并且val在這種情況下只能是字串?
uj5u.com熱心網友回復:
為了使它作業,你想changeObj成為一個通用函式:
const changeObj = <K extends keyof ITest>(
field: K, val: ITest[K]
) => obj[field] = val; // okay
該field引數的型別的K,這是一個型別引數的約束來keyof ITest。當您呼叫 時changeObj(),編譯器將K根據傳入的內容進行推斷field。然后val將檢查引數ITest[K],如果您使用型別的鍵進行索引, 您將獲得的值ITest的型別K:
changeObj("name", "hey") // okay
changeObj("name", 123) // error, number not a string
這使您不太可能將錯誤的內容傳遞到changeObj. 但這并不能完全阻止它;如果field是聯合型別,那么編譯器也將接受val類似聯合型別的 a,這可能會導致問題:
changeObj(Math.random() < 0.99 ? "name" : "anotherProp", 123); // okay?
// uh oh, very good chance of a problem
這種不健全只是 TypeScript 的一部分。問題的出現頻率不足以用語言本身來解決。
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/409687.html
標籤:
