【问题标题】:TypeScript Iterate over object and create a type from the valuesTypeScript 遍历对象并从值创建一个类型
【发布时间】:2021-06-02 04:48:47
【问题描述】:

鉴于我有这样的对象:

const props = [
    { name: 'car', list: { brand: 'audi', model: 's4' }
    { name: 'motorcycle', list: { type: 'ktm', color: 'orange' }
] as constant;

我想创建一个代表这样的类型:

type Props = {
    car?: 'brand' | 'model',
    motorcycle?: 'type' | 'color'
};

我得到的最接近的是这样的:

type Props = Partial<Record<typeof props[number]['name'], typeof props[number]['list']>

但返回如下内容:

type Props = {
    car?: { brand: 'audi', model: 's4' } | { type: 'ktm' | color: 'orange' } | undefined,
    motorcycle?: { brand: 'audi', model: 's4' } | { type: 'ktm' | color: 'orange' } | undefined
}

我怎样才能达到预期的效果?

【问题讨论】:

    标签: javascript typescript types typescript-typings


    【解决方案1】:

    您可以使用 TypeScript 4.1 (docs) 中引入的 key remapping 来实现此目的:

    type IndexKeys<T> = Exclude<keyof T, keyof []>
    type ListProp = { name: string, list: object }
    type GetName<P> = P extends ListProp ? P['name'] : never
    type GetListKeys<P> = P extends ListProp ? keyof P['list'] : never
    
    type PropsFromList<PropList extends ReadonlyArray<ListProp>> = {
      [i in IndexKeys<PropList> as GetName<PropList[i]>]?: GetListKeys<PropList[i]>
    }
    
    type Props = PropsFromList<typeof props>
    // Inferred type:
    // Props: {
    //     car?: "brand" | "model" | undefined;
    //     motorcycle?: "type" | "color" | undefined;
    // }
    

    请注意,就像使用Partial 时一样,可选属性类型会获得一个额外但无害的| undefined

    TypeScript playground

    【讨论】:

    • 很高兴为您提供帮助!第二件事似乎是可能的,但为了清楚这个问题,我建议为它创建一个新问题。
    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2013-03-02
    • 1970-01-01
    • 2020-08-02
    • 2018-09-04
    • 2021-10-21
    • 2020-10-30
    • 1970-01-01
    相关资源
    最近更新 更多