【问题标题】:Restrict interface's key types to those of another interface's values将接口的键类型限制为另一个接口的值
【发布时间】:2023-03-11 02:26:01
【问题描述】:

This playground example 描述了我正在尝试做的事情,但实际上我试图将一个对象的可能键限制为另一个对象的值。

这可能吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    我能得到的最接近的是这个

    type accessor = "surname" | "firstname"
    
    interface IData { 
      title: string;
      accessor: accessor;
    }
    
    type ICell = Record<accessor, string>
    

    【讨论】:

    • 感谢 Klas,不幸的是,我不知道访问器的值是什么,因为我使用的是泛型,因此您的解决方案将无法正常工作
    • 你是说accessor的值是在运行时任意给定的?我认为您不能以此为基础。 TypeScript 只能作用于编译时信息(因为它只在编译期间有效)
    【解决方案2】:

    在 TypeScript 中无法根据运行时值定义类型,因为所有类型在运行时都会被删除。你所要求的完全是不可能的。

    考虑:如果这个对象是从一个返回随机值的网络服务器获取的呢?编译将如何工作?您需要连接到互联网吗?由于没有运行时类型检查,它根本不起作用。

    如您所愿,要在运行时完成此操作,您可以使用普通的 javascript。例如:

    const accessors = data.map(o => o.accessor);
    
    for (const cell of cells) {
        for (const key in cell) {
            if (!accessors.includes(key)) {
                // throw a runtime error
                throw new Error("This key is not a valid accessor!"); 
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您在编译时知道IData 的类型,您可以有点这样做。所以你需要一些类似的东西:

      const data = [
        {
          title: "First name",
          accessor: "firstname",
        },
        {
          title: "Last name",
          accessor: "surname",
        }
      ] as const
      
      type Accessors = typeof data[number]["accessor"]
      
      type ICell = Record<Accessors, string>
      
      const cells: ICell[] = [
        {
          firstname: "Davy",
          surname: "James"
        },
        {
          firstname: "Billy",
          surname: "Cricket"
        }
      ]
      

      如果您在编译时不知道data 的结构,就像其他答案指出的那样,您不能这样做。此外(与任何其他对象一样)您必须检查在运行时创建的任何其他数据是否符合 ICell 数据类型,如果您正在尝试这样做,您实际上无法在运行时检查它。

      【讨论】:

        猜你喜欢
        • 2018-07-23
        • 2017-05-28
        • 1970-01-01
        • 2021-04-13
        • 2021-07-22
        • 2015-08-18
        • 2022-11-28
        • 2020-10-28
        • 1970-01-01
        相关资源
        最近更新 更多