我正在尝试学习TS,但遇到了一个奇怪的情况。
我有一个属性设置为不可枚举的对象:
let person = {
name: 'Harry'
}
Object.defineProperty(person,'salary',{enumerable: false, value : 15});
console.log(person.salary); // 15
这在运行时有效,但是,编译器会出错:
类型"{name:string;}"上不存在属性"salary">
这是预期的。
我可以绕过这种设置——任何类型的人都可以,但这感觉不是一个干净的解决方案。
还有别的办法吗?非null断言运算符对此不起作用。
如果有人能分享一些这方面的知识,我将不胜感激。
虽然您可以更改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; }
,而不是难看的交集。