JavaScript有物件包裝器,可以讓我檢查原始類型的"屬性"是否存在,那麼我該如何讓TypeScript也能像這樣運作呢?
P粉797855790
P粉797855790 2023-07-28 18:48:38
0
1
428
<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>
P粉797855790
P粉797855790

全部回覆(1)
P粉957723124

你說得對,TypeScript不允許你存取它不知道變數類型上可能存在的屬性。如果該類型是聯合類型,那麼在TypeScript允許你存取之前,該屬性必須存在於該聯合類型的所有成員上。

但是可以透過各種方法來縮小變數的類型。例如,你可以先檢查值是否為true,如果不是,則TypeScript會將聯合類型縮小為僅為ValidationError。

通常,另一個選擇是使用in運算符,但在這種情況下,聯合類型不僅包含物件類型,所以TypeScript不允許使用它。

你也可以定義一個自訂類型保護(或使用庫中提供的類型保護,如果存在的話),但對於這種簡單的情況來說,這似乎可能是你想要的工作量有點太大。

正如我提供的TypeScript文件詳細說明的那樣,還有其他縮小類型的方法。像你提到的,檢查typeof運算子的結果也是其中的一種方法。

這個例子只是宣告了一個型別保護存在,而不是實作一個,但是下面是你可以使用每種方法來縮小result變數類型的方式:

declare type ValidationError = { err: unknown };
declare function isValidationError(val: unknown): val is ValidationError;

declare const XMLValidator: {
  validate(message: unknown): true | ValidationError
};

const message = 'test message';

const result = XMLValidator.validate(message)

// You can check first if the result is `true`
if (result === true) {
  // Handle success
} else {
  // Then the `else` branch knows it much be a `ValidationError`
  console.error(result.err);
}

// Normally allowed, but not in this case. Error:
// Type 'true | ValidationError' is not assignable to type 'object'
if ('err' in result) {
  console.error(result.err)
}

if (isValidationError(result)) {
  console.error(result.err);
}

TypeScript Playground

#

雖然它們通常最好避免使用,但你也可以使用TypeScript的as關鍵字來進行型別斷言。

之所以最好避免使用這些類型斷言,是因為你告訴TypeScript將一個類型視為其他類型。因此,透過這樣做,你可能會犧牲類型安全性。


console.error((result as ValidationError).err);

然而,在你對情況的理解比TypeScript編譯器更好的情況下,這是你可以使用的工具,以向它提供更多資訊。

就我個人而言,我發現這是一種有幫助的方法,總是留下註釋解釋為什麼使用了類型斷言,提及其安全性基於的任何假設。

此外,在這種情況下,使用類型斷言來檢查屬性不會縮小result變數的類型,所以這種方法可能不完全符合你的需求。

#
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!