如何为对象的动态属性设置一个好的条件

How to set a good condition for dynamic property of object

我有一个对象数组:

export const inputsArray: InputAttributes[] = [
    {
        label: 'Name',
        type: 'text',
        name: 'name',
        required: true
    },
    {
        label: 'User name',
        type: 'text',
        name: 'username',
        required: true
    },
    ...
]

并像这样映射它:

const inputs = inputsArray.map(input => {
    const value = (input.name === 'street' || input.name === 'city' || input.name === 'zipcode')  // <=  PROBLEM : NOT EFFECTIVE CONDITION!
        ? user?.address?.[input.name] 
        : user?.[input.name]   // <= TYPESCRIPT PROBLEM 

    return (
        <Input
            key={input.name}
            defaultValue={value} 
            input={input}
            disabled={disabled}
            onChange={hadndleChange}
        />
    )
})

用户信息:

export interface User {
    id: number,
    name: string,
    username: string,
    email: string,
    address: {
        street: string,
        city: string,
        zipcode: string,
    }
    phone: string,
    website: string,
    company: {
        name: string
    }
}
  1. 如您所见,在 map 方法中我有一个值条件。但这并不好,因为如果用户对象在 address 或 company 或其他 属性 以对象为值的内部有更多附加属性,我需要在其中放置更多条件。有更好的模式吗?
  2. user?.[input.name] 打字稿说“类型 'string' 不能用于索引类型 'Users'”。我可以通过在用户界面中设置 [key: string] : any 来避免这个问题,但是有没有更好的模式?

如果需要输入属性接口:

export interface InputAttributes {
    label: string,
    type: string,
    name: string,
    pattern?: string,
    required: boolean
}

将值存储在数组中,然后使用 Array.prototype.some()。这样您就可以支持任意数量的名称。

const names = ['street', 'zipcode', 'city'];
const value = names.some((name) => input.name === name) ? user?.address?.[input.name] : user?.[input.name];

你应该像这样修改InputAttributes界面:

type DeepKeyOf<T> = {
  [K in keyof T]: T[K] extends Record<string, any> ? DeepKeyOf<T[K]> : K
}[keyof T]

export interface InputAttributes {
    label: string,
    type: string,
    name: DeepKeyOf<User>,
    pattern?: string,
    required: boolean
}

现在 TypeScript 知道 name 属性 必须包含 User.

的一些键