【问题标题】:How to check type of a JSON object against typescript interface in React如何在 React 中根据 typescript 接口检查 JSON 对象的类型
【发布时间】:2020-11-01 09:30:57
【问题描述】:

我有一个结果 JSON 对象被传递给一个函数,我需要根据 Typescript 接口定义模型检查它的类型,以便在显示它之前执行特定的渲染更改。

我面临一个问题,字符串在通过检查时匹配所有接口类型,使用 (jsonResult as TypeScriptInterfaceName) 并且随后根本不提供正确的值。

我也尝试了类转换器库,但没有成功。根据打字稿定义显式检查字符串并使其失败的最佳方法是什么。

谢谢。

interface ParentOne {
    id: string;
    title: string;
    child: Child
}
interface Child {
    id: string;
    title: string;
}
**JSON ONE**
{
    id: value,
    title: value,
    child: [{}],
}


interface ParentTwo {
    id: string;
    title: string;
    directory: Directory
}
interface Directory {
    id: string;
    title: string;
}

**JSON TWO**
{
    id: value,
    title: value,
    directory: [{}],
}

【问题讨论】:

  • 能否添加一些示例 JSON 数据、Type 接口和错误消息?
  • @codingwithmanny 我试图简单地使用以下方法: if (JSON ONE as ParentOne) { do something } else if (JSON TWO as ParentTwo) { do another }
  • JSON 是一个字符串,所以检查类型是没有意义的。如果您的意思是检查解析的 JSON,那么您说的是 JavaScript 对象,而不是 JSON。
  • 您在运行时没有这些类型,因此您无法在运行时检查它们。
  • @Victory 感谢您的提示。那么处理这种情况的最佳方法是什么。在以这种方式传递和检查对象之前向对象附加一个标志,或者是否有更简洁的解决方案。

标签: javascript reactjs typescript


【解决方案1】:

当您解析 JSON 时,结果类型将为 any。类型信息在运行时不存在,因此 Typescript 无法帮助您。

我们要做的是创建一个描述 JSON 文件的 JSON-Schema 文件,然后我们使用像 ajv 这样的 JSON-Schema 验证器来验证传入的 JSON 对象是否与该架构匹配。

然后我们使用json-schema-to-typescript 之类的工具根据模式生成类型。

我们的验证函数最终看起来像这样:

function validateBody<T>(body: unknown, jsonSchemaId: string): asserts body is T {

   // Do validation or throw error

}

这意味着从单个 JSON-Schema 中,我们得到:

  1. 后端的打字稿类型
  2. 前端的打字稿类型
  3. 文档
  4. 存在有用错误的服务器端验证器。
  5. 类型安全(验证后)

【讨论】:

    【解决方案2】:

    由于您在运行时没有接口定义,因此您不能指望它们进行完整性检查,您可能会执行以下操作。

    给出一些有用的接口

    interface ParentOne {
        id: string;
        title: string;
        child: Child
    }
    interface Child {
        id: string;
        title: string;
    }
    
    interface ParentTwo {
        id: string;
        title: string;
        directory: Directory
    }
    interface Directory {
        id: string;
        title: string;
    }
    

    我们想要一种方法来使用这些漂亮的界面

    const processParentOne = (p: ParentOne) => {
      console.log(p.child);
    }
    
    const processParentTwo = (p: ParentTwo) => {
      console.log(p.directory);
    }
    

    所以我们一可以推断出类型就转换它们

    const processionJson = (data: any) => {
      if (!!data.child) {
        processParentOne(data as ParentOne);
      } else if(!!data.directory) {
        processParentTwo(data as ParentTwo);
      }
    }
    

    这样我们就可以做类似的事情

    const p1: ParentOne = {
      id: 'po',
      title: "p1",
      child: {
        id: 'chopo',
        title: 'little'
      }
    }
    
    const p2: ParentTwo = {
      id: 'pt',
      title: 'p2',
      directory: {
        id: 'dirpt',
        title: 'dict'
      }
    }
    
    // Remove all the type info for example
    const json = (Math.random() < .5) 
      ? JSON.stringify(p1) : JSON.stringify(p2);
    
    // pass along "unknown" data type
    processionJson(JSON.parse(json))
    
    

    【讨论】:

    • 感谢您的详尽解释,非常感谢!
    • @sam 如果这有助于您投票并标记为已回答。
    猜你喜欢
    • 1970-01-01
    • 2018-08-26
    • 2021-07-31
    • 2020-04-26
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多