JavaScript有物件包裝器,可以讓我檢查原始類型的"屬性"是否存在,那麼我該如何讓TypeScript也能像這樣運作呢?
P粉797855790
2023-07-28 18:48:38
<p>XMLValidator.validate的回傳值要不是true,就是ValidationError(這並不完全準確,請查看我的更新),而ValidationError具有err屬性。 </p>
<pre class="brush:php;toolbar:false;">validate( xmlData: string, options?: validationOptionsOptional): true | ValidationError</pre>
<p>因為JavaScript使用物件包裝器來表示布林原始值,所以我可以透過檢查err屬性是否存在來判斷驗證是否成功。 </p>
<pre class="brush:php;toolbar:false;">const result = XMLValidator.validate(message)
if (result.err) { // How do I make it work in ts?
console.log(`invalid XML)
} else {
console.log(`XML)
}</pre>
<p>但是TypeScript不允許我這樣做,它會報錯:"true"類型上不存在屬性'err'。 </p><p>我不喜歡先檢查回傳類型的想法,因為我覺得它很囉嗦,而且實際上沒有傳回值類型的定義(請查看我的更新)。我應該如何編寫盡可能簡潔的TypeScript程式碼? </p><p>--- 更新 ---</p><p>我進一步檢查了validator.js的程式碼。 </p><p><br /></p>
<pre class="brush:php;toolbar:false;">const isValid = validateAttributeString(attrStr, options);
if (isValid !== true) {
return getErrorObject(...);
}
…
function getErrorObject(code, message, lineNumber) {
return {
err: {
code: code,
msg: message,
line: lineNumber.line || lineNumber,
col: lineNumber.col,
},
};
}</pre>
<p>所以看起來我只能在這裡使用 if (typeof result == "boolean"),但我希望有一個"通用"的解決方案來回答我的問題。 </p>
你說得對,TypeScript不允許你存取它不知道變數類型上可能存在的屬性。如果該類型是聯合類型,那麼在TypeScript允許你存取之前,該屬性必須存在於該聯合類型的所有成員上。
但是可以透過各種方法來縮小變數的類型。例如,你可以先檢查值是否為true,如果不是,則TypeScript會將聯合類型縮小為僅為ValidationError。
通常,另一個選擇是使用in運算符,但在這種情況下,聯合類型不僅包含物件類型,所以TypeScript不允許使用它。
你也可以定義一個自訂類型保護(或使用庫中提供的類型保護,如果存在的話),但對於這種簡單的情況來說,這似乎可能是你想要的工作量有點太大。
正如我提供的TypeScript文件詳細說明的那樣,還有其他縮小類型的方法。像你提到的,檢查typeof運算子的結果也是其中的一種方法。
這個例子只是宣告了一個型別保護存在,而不是實作一個,但是下面是你可以使用每種方法來縮小result變數類型的方式:
TypeScript Playground
#雖然它們通常最好避免使用,但你也可以使用TypeScript的as關鍵字來進行型別斷言。
之所以最好避免使用這些類型斷言,是因為你告訴TypeScript將一個類型視為其他類型。因此,透過這樣做,你可能會犧牲類型安全性。
然而,在你對情況的理解比TypeScript編譯器更好的情況下,這是你可以使用的工具,以向它提供更多資訊。
就我個人而言,我發現這是一種有幫助的方法,總是留下註釋解釋為什麼使用了類型斷言,提及其安全性基於的任何假設。
此外,在這種情況下,使用類型斷言來檢查屬性不會縮小result變數的類型,所以這種方法可能不完全符合你的需求。
#