简体   繁体   English

Typescript: 过滤 keyof 类型参数

[英]Typescript : Filter on keyof type parameter

I'm using typescript 3.8.3 and try to dynamically find the keys of a certain type and use them to produce an other object.我正在使用 typescript 3.8.3 并尝试动态查找某种类型的密钥并使用它们来生成另一个 object。

I have a Detail object and want to use it to dynamically generate a Column object only based on the properties of type Desc .我有一个Detail object 并希望使用它仅基于Desc类型的属性动态生成一个Column object 。 Here is a simplified code of what i want to do:这是我想要做的简化代码:

// 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

}

How can i benefit from the help of the compiler to construct my config object and thus be able to detect any errors if my Detail object changes?我如何从编译器的帮助中受益来构建我的config object 并因此能够在我的Detail object 更改时检测到任何错误?

Thanks !谢谢 !

In order to exclude some columns for a mapped type, we need to use an intermediate helper type, allowing us to select only the keys respecting our condition, T[K] extends Desc :为了排除映射类型的某些列,我们需要使用中间辅助类型,允许我们 select 仅符合我们条件的T[K] extends Desc

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

Given this, ColumnConfig just need to map over this generic type instead of the original keyof T :鉴于此, ColumnConfig只需要 map 超过此泛型类型,而不是原始keyof T

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

Then your config object will be correctly validated:然后您的配置 object 将被正确验证:

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

If you need to allows arrays too (ie Address[] instead of Address ), you can change the helper type, checking for T extends Desc[] .如果您也需要允许arrays (即Address[]而不是Address ),您可以更改帮助器类型,检查T extends Desc[] Furthermore, you will need an UnboxArray helper too, to extract item value Order[] -> Order for your column config:此外,您还需要一个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]>>[]
};

You can see it at work in the following playground: Playground Link您可以在以下操场上看到它: Playground Link

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM