我正在嘗試學習 TS,但遇到了一個奇怪的案例。
我有一個屬性設定為不可列舉的物件:
let person = {
name: 'Harry'
}
Object.defineProperty(person,'salary',{enumerable: false, value : 15});
console.log(person.salary); // 15
這在運行時有效,但是,編譯器會出錯:
型別 '{ name: string; 上不存在屬性 'salary' }'
這是預期的。
我可以繞過這個設定任何人的型別,但它感覺不是一個干凈的解決方案。
還有另一種方法嗎?非空斷言運算子對此不起作用。
如果有人能分享一些這方面的知識,我將不勝感激。
uj5u.com熱心網友回復:
雖然您可以更改 的型別注釋person,但可能像:
let person: { name: string; salary?: number } = {
name: 'Harry'
};
甚至:
let person = {
name: 'Harry'
} as { name: string; salary: number };
最安全的方法可能是(ab)在 3.7 版本中使用斷言函式:
function defineProperty<
O,
Property extends PropertyKey,
Value
>(o: O, key: Property, attributes: PropertyDescriptor & ThisType<any> & { value: Value }): asserts o is O & Record<Property, Value> {
Object.defineProperty(o, key, attributes);
}
它本質上是一個包裝函式,Object.defineProperty它告訴 TypeScript,如果這個函式沒有拋出錯誤,那么給定值的型別o是O & Record<Property, Value>.
所以當你使用它時,你會得到一個像這樣的型別:
defineProperty(person,'salary',{enumerable: false, value : 15});
person
// ^? { name: string; } & Record<"salary", number>
操場
如果你真的想要,你還可以通過將斷言更改為這樣來使生成的型別更清晰:
asserts o is (O & Record<Property, Value> extends infer T extends O ? { [K in keyof T]: T[K] } : O)
正如您在將滑鼠懸停在 上時看到的person那樣,該型別現在{ name: string; salary: number; }不是丑陋的交叉點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/508379.html
標籤:打字稿
