【问题标题】:Type Definition for JSON file Keys with Prefix using TypeScript使用 TypeScript 对带有前缀的 JSON 文件键的类型定义
【发布时间】:2021-07-26 02:27:28
【问题描述】:

我正在将 JSON 文件导入到我的 TypeScript 程序中,如下所示:(我在 tsconfig.json 中启用了 resolveJsonModule

import data from './sample.json';

很高兴,我注意到从 JSON 文件接收到的对象是强类型的。然后我编写了一个函数,该函数根据参数访问所述 JSON 对象的某个键:

export const get = (key: keyof typeof data): void => {
    console.log(data[key]); // example code
};

这按预期工作,我的函数的使用者会知道 JSON 文件中接受/包含哪些值。问题来了:我希望我的函数的使用者只能访问我前缀的某些键(在以下示例中,前缀是 prefix_):

export const get = (key: keyof typeof data): void => {
    console.log(data[`prefix_${key}`]);
};

我必须如何更改我的类型定义才能使其仍然有效?

【问题讨论】:

    标签: json typescript object


    【解决方案1】:

    TypeScript 4.3 之前

    从 TypeScript 4.2 开始,无法在使用字符串函数的情况下执行条件类型,因此我不知道如何指定以前缀开头的键。

    我能想到的最好的方法是使用 Pick utility type 从所有可能属性的交集和 json 文件的派生类型创建一个新类型。

    在下面的示例中,我导入了两个示例 json 文件。接下来,我指定所有可能的键以保留在字符串文字类型中。然后使用 Pick 从这两个文件中创建两种类型。为了让 Pick 工作,我必须在第二个参数中传递一个类型,它是派生文件类型和 PublicPrefix 类型的键的交集。

    import data1 from './sample1.json'; // { x: 1, prefix_A: 2, prefix_B: 3 }
    import data2 from './sample2.json'; // { y: 1, prefix_B: 2, prefix_C: 3 }
    type PublicPrefix = 'prefix_A' | 'prefix_B' | 'prefix_C';
    export type Data1 = Pick<typeof data1, keyof typeof data1 & PublicPrefix>;
    // Data1 = { prefix_A: number, prefix_B: number }
    export type Data2 = Pick<typeof data2, keyof typeof data2 & PublicPrefix>;
    // Data2 = { prefix_B: number, prefix_C: number }
    

    如果 data1 具有属性 prefix_Aprefix_B,而 data2 具有属性 prefix_Bprefix_C,则结果类型将是 Data1 = { prefix_A, prefix_B }Data2 = { prefix_B, prefix_C },所有其他键都被排除在外。

    TypeScript 4.3 中的模板字符串文字

    TypeScript 4 引入了模板字符串文字,在 4.3 版中,它们增强了功能,因此您可以指定上下文类型的模板。这允许您在模板中指定一个类型,将模板的这些部分扩展为对该类型有效的任何内容。

    在下面的示例中,创建了一个模板字符串文字,它以 prefix_ 开头,后跟任何字符串。通过以与上例相同的方式使用 Pick,生成的类型将仅包含以 prefix_ 开头的属性。

    import data from './sample.json';
    type PublicPrefix = `prefix_${string}`;
    export type Data1 = Pick<typeof data, keyof typeof data & PublicPrefix>;
    

    【讨论】:

      猜你喜欢
      • 2019-12-21
      • 2020-02-08
      • 1970-01-01
      • 2018-10-09
      • 2021-11-01
      • 2018-05-29
      • 1970-01-01
      • 1970-01-01
      • 2021-08-11
      相关资源
      最近更新 更多