【问题标题】:Typescript : Filter on keyof type parameter打字稿:过滤keyof类型参数
【发布时间】:2020-08-13 20:04:17
【问题描述】:

我正在使用 typescript 3.8.3 并尝试动态查找某种类型的键并使用它们来生成另一个对象。

我有一个Detail 对象,并希望使用它仅基于Desc 类型的属性动态生成Column 对象。 这是我想做的简化代码:

// Model
interface Desc {
    creationDate: Date;
}

interface Address extends Desc {
    zipCode: number;
    adressName: string;
}

interface Order extends Desc {
    id: number;
    orderName: string;
}

interface Detail {
    name: string;
    address: Address[];
    orders: Order[];
}
// Table column configuration
interface Column<T> {
    field: keyof T;
    active: boolean;
}

type ColumnConfig<T> = { [P in keyof T]: Column<T[P] extends Desc ? P : never>[] };

const config: ColumnConfig<Detail> = {
    address: [
        {
            field: "zipCode",
            active: true 
        }, 
        {
            field: "addressName",
            active: true
        }
    ],
    order: [
        {
            field: "id",
            active:false
        },
        {
            field: "orderName",
            active: false
        }
    ],
    // Detail.name should not be available but it is

}

如何从编译器的帮助中受益来构造我的config 对象,从而能够在我的Detail 对象发生变化时检测到任何错误?

谢谢!

【问题讨论】:

  • 嗨 Nainpo,我看到您将 address 声明为一个数组。那么你需要像Column&lt;Address&gt;[] 这样的东西吗?您能否添加一个您想要类型的示例作为输出?
  • 事实上这是一个错字,直到现在我一直想要一个对象数组,但是 UnboxArray 有一天会很有用! :)

标签: typescript


【解决方案1】:

为了排除映射类型的某些列,我们需要使用中间辅助类型,允许我们根据条件仅选择 T[K] extends Desc

type ConfigurableColumnsKeys<T extends object> = {
  [K in keyof T]: T[K] extends Desc ? K : never
}[keyof T];

鉴于此,ColumnConfig 只需要映射这个泛型类型,而不是原来的 keyof T

type ColumnConfig<T extends object> = {
  [P in ConfigurableColumnsKeys<T>]: Column<P>[] 
};

然后您的配置对象将被正确验证:

  // Error
  name: [
    { field: 'abc', active: true }
  ]

如果您也需要允许数组(即Address[] 而不是Address),您可以更改帮助程序类型,检查T extends Desc[]。此外,您还需要一个 UnboxArray 帮助器,为您的列配置提取项目值 Order[] -> Order

type ConfigurableColumnsKeys<T extends object> = {
  [K in keyof T]: T[K] extends Desc ? K : T[K] extends Desc[] ? K : never
}[keyof T];

type UnboxArray<T> = T extends Array<infer V> ? V : T;

type ColumnConfig<T extends object> = {
  [P in ConfigurableColumnsKeys<T>]: Column<UnboxArray<T[P]>>[]
};

您可以在以下操场上看到它:Playground Link

【讨论】:

  • 谢谢你,这是我正在寻找的技巧!我还有一个问题,如果我忘记了其中一个必填字段,是否会出现编译器错误?即ordersaddress ?
  • 事实上它已经工作了,谢谢你的帮助@leonardfactory!
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2022-08-21
  • 2022-01-18
  • 1970-01-01
  • 2022-09-24
  • 2023-02-16
  • 2018-05-02
相关资源
最近更新 更多