JavaScript有对象包装器,可以让我检查原始类型的"属性"是否存在,那么我该如何让TypeScript也能像这样工作呢?
P粉797855790
P粉797855790 2023-07-28 18:48:38
0
1
479
<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变量的类型,所以这种方法可能不完全符合你的需求。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板