如何使用动态对象数组中的键动态键入对象

我有一个函数可以减少属性数组并构建一个对象:


type FieldProps = {

  name: string;

  value: string;

  required: boolean;

  styles?: object;

  className?: string

}


const fields: FieldProps[] = [

  {

    name: "firstName",

    value: "Bob",

    required: true,

    styles: { width: "100%"}

  },

  {

    name: "lastName",

    value: "Smith",

    required: true,

    className: "example"

  },

  {

    name: "city",

    value: "Tulsa",

    required: true,

  },

  {

    name: "state",

    value: "OK",

    required: true,

  },

]


const parseFields = <T extends any[], K extends object = {}>(fields: T): K => {

  try {

    if (!fields || (fields && fields.length < 0)) throw new Error("You must supply an array of fields!");


    const parsedFields = fields.reduce((acc, { name, value }: { name: string, value: string}) => {

      switch (name) {

        case "city":

        case "street":

        case "state":

        case "suite":

        case "zipCode": {

          acc["address"] = acc["address"] || {};

          if (value) acc.address[name] = value;

          break;

        }

        default: {

          acc[name] = value;

          break;

        }

      }

      return acc;

    }, {} as K);


    return parsedFields;

  } catch (err) {

    throw String(err);

  }

};


const userDetails = parseFields(fields);

截至目前,悬停在上方userDetails会显示一个空对象类型( {}),理想情况下应该是:


{

  "firstName": string,

  "lastName": string,

  "address": {

    "city": string,

    "state": string

  }

}

我如何重构函数以获取类型FieldProps[]并让它返回动态类型的对象?


精慕HU
浏览 176回答 3
3回答

有只小跳蛙

这个答案非常(过度)复杂,但你最终会得到这种类型:const userDetails = parseFields(fields);type Z = typeof userDetails;// type Z = {//&nbsp; &nbsp; &nbsp;address: {//&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;city: "Tulsa" | "Norman"; // Added to test//&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;state: "OK";//&nbsp; &nbsp; &nbsp;};// } & {//&nbsp; &nbsp; &nbsp;firstName: "Bob";//&nbsp; &nbsp; &nbsp;lastName: "Smith";// }它需要制作fields as const:const fields = [&nbsp; ...] as const;还有……实际的打字:type AddressKeys = 'city' | 'street' | 'state' | 'suite' | 'zipCode';type _ParseFieldsResultKeys<T extends readonly FieldProps[]> = {&nbsp; [K in keyof T]: T[K] extends { name: string } ? T[K]['name'] : never;}[Exclude<keyof T, keyof []>];type _GetParseFieldResultValue<T extends readonly FieldProps[], N> =&nbsp; Extract<T[keyof T], { name: N }> extends { value: infer V } ? V : never;type ParseFieldsResult<T extends readonly FieldProps[]> = {&nbsp; address: {&nbsp; &nbsp; [N in Extract<_ParseFieldsResultKeys<T>, AddressKeys>]: _GetParseFieldResultValue<T, N>;&nbsp; }} & {&nbsp; [N in Exclude<_ParseFieldsResultKeys<T>, AddressKeys>]: _GetParseFieldResultValue<T, N>;};const parseFields = <T extends readonly FieldProps[]>(fields: T): ParseFieldsResult<T> => {使用它可能不是一个好主意。但是:游乐场链接编辑:意识到我们不需要实际的字符串文字类型,只需要string我们可以摆脱_GetParseFieldResultValue并仍然得到的值:type Z = {&nbsp; &nbsp; address: {&nbsp; &nbsp; &nbsp; &nbsp; city: string;&nbsp; &nbsp; &nbsp; &nbsp; state: string;&nbsp; &nbsp; };} & {&nbsp; &nbsp; firstName: string;&nbsp; &nbsp; lastName: string;}

长风秋雁

在 parseFields 函数中,你有一个 K.. 的返回类型,它是一个空对象......你不应该传入 FieldProps 吗?const parseFields = <T extends any[], K extends object = {}>(fields: T): **FieldProps** => {

智慧大石

您在此处使用通用方法,并将 K 的默认类型设置为 {},这就是您在悬停时看到 {} 的原因。您可以通过正确调用该方法来实现您正在寻找的东西。像这样:const userDetails = parseFields<FieldProps[], {&nbsp; "firstName": string,&nbsp; "lastName": string,&nbsp; "address": {&nbsp; &nbsp; "city": string,&nbsp; &nbsp; "state": string&nbsp; }}>(fields);&nbsp;&nbsp;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript