代码之家  ›  专栏  ›  技术社区  ›  Stefan Zhelyazkov

无法获取TypeScript以导入具有正确类型的JSON

  •  1
  • Stefan Zhelyazkov  · 技术社区  · 4 年前

    我有以下文件 test.json 我希望以打印形式导入它。

    {
      "items": [
        {
          "kind": "youtube#video",
          "thumbnails": {
            "default": {
              "url": "https://i.ytimg.com/vi/WnVAkK876rA/default.jpg",
              "width": 120,
              "height": 90
            }
          }
        },
        {
          "kind": "youtube#video",
          "thumbnails": {
            "default": {
              "url": "https://i.ytimg.com/vi/jhTpc7nFtfI/default.jpg",
              "width": 120,
              "height": 90
            },
            "maxres": {
              "url": "https://i.ytimg.com/vi/jhTpc7nFtfI/maxresdefault.jpg",
              "width": 1280,
              "height": 720
            }
          }
        }
      ]
    }
    

    这是我的 App.tsx :

    import { TestData } from './Types';
    import * as testData from './test.json'
    const ttt: TestData = testData;
    

    这是 Types.ts

    export interface TestData {
      items: TestDataPiece[]
    }
    
    export interface TestDataPiece {
      kind: string,
      thumbnails: {[key: string]: {
        url: string,
        width: number,
        height: number
      }}
    }
    

    在我的 tsconfig.json 我使用 "resolveJsonModule": true 。但是我得到了这个错误:

    [tsl] ERROR in C:\Users\home\IdeaProjects\yt-glasat\src\App.tsx(11,7)
          TS2322: Type '{ items: ({ kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres?: undefined; }; } | { kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres: { ...; }; }; })[]; }' is not assignable to type 'TestData'.
      Types of property 'items' are incompatible.
        Type '({ kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres?: undefined; }; } | { kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres: { ...; }; }; })[]' is not assignable to type 'TestDataPiece[]'.
          Type '{ kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres?: undefined; }; } | { kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres: { ...; }; }; }' is not assignable to type 'TestDataPiece'.
            Type '{ kind: string; thumbnails: { default: { url: string; width: number; height: number; }; maxres?: undefined; }; }' is not assignable to type 'TestDataPiece'.
              Types of property 'thumbnails' are incompatible.
                Type '{ default: { url: string; width: number; height: number; }; maxres?: undefined; }' is not assignable to type '{ [key: string]: { url: string; width: number; height: number; }; }'.
                  Property '"maxres"' is incompatible with index signature.
                    Type 'undefined' is not assignable to type '{ url: string; width: number; height: number; }'.
    
    2 回复  |  直到 4 年前
        1
  •  2
  •   T.J. Crowder    4 年前

    问题是推断的数据类型具有 maxres 的财产 可选择的 ,这意味着它的类型是 {url: string; width: number; height: number} | undefined 。但是您的缩略图对象类型不允许 undefined 用于具有索引签名的对象的值。

    其中任何一个都会使错误消失:

    1. 确保JSON中的所有相关对象都具有 最大值 所有物或
    2. 允许 未定义的 在缩略图对象上;或
    3. 在执行分配时使用类型断言,可能有运行时检查的支持

    我猜你不能做#1,也不想做#2,所以你只剩下类型断言:

    const ttt = testData as TestData;
    

    不过,类型断言通常是最后的解决方案;您可以使用运行时检查对其进行备份以进行验证 testData 以确保它适合使用类型保护函数或类型断言函数的接口。

    例如:

    function assertIsValidTestData(data: any): asserts data is TestData {
        if (!Array.isArray(data) ||
            data.some(element => {
                return typeof element !== "object" ||
                       typeof element.kind !== "string" ||
                       typeof element.thumbnails !== "object" ||
                       Object.values(element.thumbnails).some(thumbnail => {
                           return typeof thumbnail !== "object" ||
                                  typeof thumbnail.url !== "string" ||
                                  typeof thumbnail.width !== "number" ||
                                  typeof thumbnail.height !== "number";
                       })
            })) {
            throw new Error(`Test data is not valid`);
        }
    }
    

    然后

    assertIsValidTestData(testData);
    const ttt: TestData = testData;
    
        2
  •  1
  •   jsejcksn    4 年前

    使用 type assertion 应该适用于您的案例:

    const ttt = testData as TestData;
    
    推荐文章