【问题标题】:How to check for the property type of an `unknown` value?如何检查“未知”值的属性类型?
【发布时间】:2021-11-19 16:38:15
【问题描述】:

我有以下函数,它可以接收未知值:

function formatReason(detail: unknown): string {
    if (detail
        && detail instanceof Object
        && detail.constructor.name === 'Object'
        && detail.hasOwnProperty('description')
        && typeof detail['description'] === 'number'
    ) {
        const output = detail['description'];
        return output;
    }

    return '';
}

detail 参数可以是任何值。如果它是具有字符串类型的description 属性的对象,则该函数应返回该属性值,否则为空字符串。

首先,您推荐使用anyunknown 作为detail 参数吗?

其次,无论我做什么,output 的类型最终都是any。如何确定是string

【问题讨论】:

    标签: typescript


    【解决方案1】:

    编辑:已被 Neon 更正。 typeguard 还不够。我更新了示例以显式断言 unknown 值而不是隐式 any


    我建议使用unknown,因为它是any 的类型安全变体,也就是说您可能想要使用类型保护来断言未知值。这意味着您正在寻找的description 属性实际上被断言为string 而不是any

    typeguard(查看操场以了解 IDescription 是什么):

    public hasDescription(obj: unknown): obj is IDescription {
        return (obj as IDescription).description !== undefined
            && typeof (obj as IDescription).description === "string";
    }
    

    在代码库中使用它会产生一个具有一些好处的 if 语句。

    if (this.hasDescription(detail)) {
        // In this if-block the TypeScript compiler actually resolved the unknown type to the type described in the guard.
        console.log(detail.description);
    }
    

    Here's 一个让您了解其工作原理的游乐场(注意如何仅将 123 输出到控制台)。


    针对您的特定问题的示例实现:

    function formatReason(detail: unknown): string {
        if (this.hasDescription(detail) {
            return detail.description;
        }
    
        return '';
    }
    
    

    【讨论】:

    • 在你的类型保护中,obj 隐含的类型为any。在您的 Playground 脚本中,您将unknown 类型值传递给它,但这并不重要,因为any 接受包括unknown 在内的所有类型。如果您在类型保护中将obj 声明为unknown,它将停止工作。但是,我假设提问者想知道您是否建议使用 unknown 作为类型保护参数的类型。
    【解决方案2】:

    在实现this suggestion 之前,没有编写此代码的好方法。与此同时,您是否更喜欢anyunknown 取决于您(如果您使用noImplicitAny,请使用一些演员表,我通常会推荐)。我不会担心output 局部变量的类型,因为无论如何你已经将函数的返回类型声明为string

    【讨论】:

      【解决方案3】:

      这真的应该内置到打字稿中!

      无论如何,这是我稍微通用的变体,如果存在,它将返回属性的字符串值。

      function getStrProp(o: unknown, prop: string): string | unknown {
          try {
              // eslint-disable-next-line @typescript-eslint/no-explicit-any
              const p = (o as any)[prop]
              if (typeof p === 'string') {
                  return p
              }
          } catch {
              // ignore
          }
          return undefined
      }
      

      我典型的错误处理用例

      try {
          httpServer = https.createServer(...)...
      } catch (err) {
          if (getStrProp(err, 'code') === 'ENOENT') {
              throw 'HTTPS certificates missing: ' + getStrProp(err, 'message')
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-21
        • 1970-01-01
        • 2018-05-15
        • 2014-02-02
        • 2020-08-01
        • 1970-01-01
        • 2016-11-04
        • 1970-01-01
        相关资源
        最近更新 更多