declare const action: { total: number } | { };
declare const defavlt: 200;
const total = (action.hasOwnProperty("total")) ? action.total : defavlt;
导致action.total
的以下TS错误:
Property 'total' does not exist on type '{ type: "NEW_CONVERSATION_LIST" | "UPDATE_CONVERSATION_LIST_ADD_BOTTOM" | "UPDATE_CONVERSATION_LIST_ADD_TOP"; list: IDRArray<RestConversationMember>; total: number | undefined; } | ... 13 more ... | { ...; }'.
Property 'total' does not exist on type '{ type: "UPDATE_URL_STATE"; updateObj: IMessagingUrlState; }'.ts(2339)
而
const total = ("total" in action) ? action.total : defavlt
有效。 TS区别对待这两种情况是否有道理?
答案 0 :(得分:4)
在问题microsoft/TypeScript#10485中,建议in
运算符充当type guard,可用于过滤并集;这是在microsoft/TypeScript#15256和released with TypeScript 2.7中实现的。
Object.prototype.hasOwnProperty()
尚未完成;如果您对此确实有强烈的想法,则可能需要file a suggestion,注意similar suggestion (microsoft/TypeScript#18282)被拒绝是因为它要求对 key 进行更有争议的缩小不是 object ...,有些人想要both (microsoft/TypeScript#20363)。并且不能保证该建议会被接受。
幸运的是,您不必等待此操作在上游实现。与in
之类的运算符不同,hasProperty()
方法只是一个库签名,可以对其进行更改以充当user-defined type guard函数。此外,您甚至不必触摸standard library definition;您可以使用declaration merging通过您自己的Object
签名来扩展hasOwnProperty()
界面:
// declare global { // need this declaration if in a module
interface Object {
hasOwnProperty<K extends PropertyKey>(key: K): this is Record<K, unknown>;
}
// } // need this declaration if in a module
此定义表示,当您检查obj.hasOwnProperty("someLiteralKey")
时,true
结果意味着obj
可分配给{someLiteralKey: unknown}
,而false
结果却没有。该定义可能并不完美,并且可能存在很多边缘情况(例如obj.hasOwnProperty(Math.random()<0.5?"foo":"bar")
意味着什么?obj.hasOwnProperty("foo"+"bar")
意味着什么?它们将做出奇怪的事情),但是它适用于您的示例:< / p>
const totalIn = ("total" in action) ? action.total : defavlt; // okay
const totalOwnProp = (action.hasOwnProperty("total")) ? action.total : defavlt; // okay
好的,希望能有所帮助;祝你好运!