Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在TypeScript中键入对象数组_Javascript_Typescript - Fatal编程技术网

Javascript 在TypeScript中键入对象数组

Javascript 在TypeScript中键入对象数组,javascript,typescript,Javascript,Typescript,使用typescript键入对象数组: 以下是接口: export interface IUser { id: string; order: number; } export interface IUsersLogin { result: number; UserId: string; } export interface IUsersUsers { id: number; order: number; } export interface IOriginalDat

使用typescript键入对象数组:

以下是接口:

export interface IUser {
  id: string;
  order: number;
}

export interface IUsersLogin {
  result: number;
  UserId: string;
}

export interface IUsersUsers {
  id: number;
  order: number;
}

export interface IOriginalData {
  Users?: IUser[];
  UsersLogins?: IUsersLogin[];
  UsersUsers?: IUsersUsers[];
}
const originalData: IOriginalData = {
  Users: [
    {
      id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
      order: 1
    },
    {
      id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
      order: 2
    }
  ],
  UsersLogins: [
    {
      result: 1,
      UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
    },
    {
      result: 0,
      UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
    }
  ],
  UsersUsers: [
    {
      id: 1,
      order: 0
    },
    {
      id: 2,
      order: 0
    }
  ]
};
在这里,我使用以下接口创建一个对象:

export interface IUser {
  id: string;
  order: number;
}

export interface IUsersLogin {
  result: number;
  UserId: string;
}

export interface IUsersUsers {
  id: number;
  order: number;
}

export interface IOriginalData {
  Users?: IUser[];
  UsersLogins?: IUsersLogin[];
  UsersUsers?: IUsersUsers[];
}
const originalData: IOriginalData = {
  Users: [
    {
      id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
      order: 1
    },
    {
      id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
      order: 2
    }
  ],
  UsersLogins: [
    {
      result: 1,
      UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
    },
    {
      result: 0,
      UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
    }
  ],
  UsersUsers: [
    {
      id: 1,
      order: 0
    },
    {
      id: 2,
      order: 0
    }
  ]
};
在这里,我操纵这个对象的数据,将其推入另一个对象:

interface IPushedDataItem {
  data: IUser | IUsersLogin | IUsersUsers;
}

type TypePushedData = Array<IPushedDataItem>;

let pushedData: TypePushedData = [];
Object.keys(originalData).forEach(item => {
  pushedData.push({
    data: originalData[item]
  });
});
接口IPushedDataItem{
数据:IUser | IUsersLogin | IUsersUsers;
}
键入TypePushedData=数组;
让pushedData:TypePushedData=[];
Object.keys(originalData).forEach(项=>{
pushedData.push({
数据:原始数据[项目]
});
});
在此过程中,我无法正确键入
pushedData
,并且它会抱怨
数据:originalData[item]

您可以在TypeScript playgound中找到:


欢迎任何帮助

这里有几个问题

originalData
没有索引签名。通常,由于TypeScript的静态类型性质,高度动态的代码(例如使用
Objct.keys
按名称遍历对象所有属性的代码)往往会出现问题,因为静态类型信息丢失,因为属性具有不同的值类型。如果你可以避免这样做,在你的情况下,这可能会更好

另一个问题是,您给了
pushedData
一种类型,该类型需要一个具有
data
属性的对象数组,但您的代码没有这样做,它将
IUser
等对象直接推送到数组中,而不是将
data
属性为
IUser
等对象的对象推送到数组中。我猜你的意思是
IPushedDataItem
是:

type IPushedDataItem  = IUser | IUsersLogin | IUsersUsers;
假设我的回答是正确的,那么您可以创建如下
pushedData

let pushedData: TypePushedData = [
    ...(originalData.Users ? originalData.Users : []),
    ...(originalData.UsersLogins ? originalData.UsersLogins : []),
    ...(originalData.UsersUsers ? originalData.UsersUsers : []),
];

这还有一个优点,就是为结果数组中的条目提供了一个定义的顺序(而对于
Object.keys
,没有按照规范保证顺序,尽管所有现代引擎对自己的属性遵循与对
getOwnPropertyKeys
相同的顺序,但这并不保证)

如果将属性设置为非可选属性(删除了
IOriginalData
中属性中的
),则复杂性会降低。那就只是:

let pushedData: TypePushedData = [
    ...originalData.Users,
    ...originalData.UsersLogins,
    ...originalData.UsersUsers,
];

如果确实希望对象具有
数据
属性(原始版本的
IPushedDataItem
),则应使用
映射

let pushedData: TypePushedData = [
    ...(originalData.Users ? originalData.Users.map(data => ({data})) : []),
    ...(originalData.UsersLogins ? originalData.UsersLogins.map(data => ({data})) : []),
    ...(originalData.UsersUsers ? originalData.UsersUsers.map(data => ({data})) : []),
];

…如果属性不是可选的,这也会更简单

  • 扩展原始数据的定义以支持索引器:
  • 将项添加到
    pushedData
    时,必须迭代键访问的项数组,因为它不是单个项:
  • 总体代码如下所示:

    export interface IUser {
      id: string;
      order: number;
    }
    
    export interface IUsersLogin {
      result: number;
      UserId: string;
    }
    
    export interface IUsersUsers {
      id: number;
      order: number;
    }
    
    export interface IOriginalData {
      Users?: IUser[];
      UsersLogins?: IUsersLogin[];
      UsersUsers?: IUsersUsers[];
    }
    
    const originalData: IOriginalData & { [key: string]: (IUser | IUsersLogin | IUsersUsers)[] } = {
      Users: [
        {
          id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
          order: 1
        },
        {
          id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
          order: 2
        }
      ],
      UsersLogins: [
        {
          result: 1,
          UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
        },
        {
          result: 0,
          UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
        }
      ],
      UsersUsers: [
        {
          id: 1,
          order: 0
        },
        {
          id: 2,
          order: 0
        }
      ]
    };
    
    interface IPushedDataItem {
      data: IUser | IUsersLogin | IUsersUsers;
    }
    
    type TypePushedData = Array<IPushedDataItem>;
    
    let pushedData: TypePushedData = [];
    Object.keys(originalData).forEach(item => {
      const subItems = originalData[item];
      if (subItems) {
        for (const subItem of originalData[item]) {
          pushedData.push({
            data: subItem
          });
        }
      }
    });
    
    
    export interface IUser {
      id: string;
      order: number;
    }
    
    export interface IUsersLogin {
      result: number;
      UserId: string;
    }
    
    export interface IUsersUsers {
      id: number;
      order: number;
    }
    
    export interface IOriginalData {
      Users?: IUser[];
      UsersLogins?: IUsersLogin[];
      UsersUsers?: IUsersUsers[];
    }
    
    export type OriginalDataUnion = IUser | IUsersLogin | IUsersUsers;
    
    const originalData: IOriginalData & { [key in keyof IOriginalData]: OriginalDataUnion[] } = {
      Users: [
        {
          id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
          order: 1
        },
        {
          id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
          order: 2
        }
      ],
      UsersLogins: [
        {
          result: 1,
          UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
        },
        {
          result: 0,
          UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
        }
      ],
      UsersUsers: [
        {
          id: 1,
          order: 0
        },
        {
          id: 2,
          order: 0
        }
      ]
    };
    
    interface IPushedDataItem {
      data: OriginalDataUnion;
    }
    
    type TypePushedData = Array<IPushedDataItem>;
    
    let pushedData: TypePushedData = [];
    for (const item of Object.keys(originalData) as (keyof IOriginalData)[]) {
      const subItems = originalData[item];
      if (subItems) {
        for (const subItem of subItems) {
          pushedData.push({
            data: subItem
          });
        }    
      }
    }
    
    尽管它还需要将
    Object.keys(originalData)
    的结果强制转换为
    (keyof IOriginalData)[]

    总体代码如下所示:

    export interface IUser {
      id: string;
      order: number;
    }
    
    export interface IUsersLogin {
      result: number;
      UserId: string;
    }
    
    export interface IUsersUsers {
      id: number;
      order: number;
    }
    
    export interface IOriginalData {
      Users?: IUser[];
      UsersLogins?: IUsersLogin[];
      UsersUsers?: IUsersUsers[];
    }
    
    const originalData: IOriginalData & { [key: string]: (IUser | IUsersLogin | IUsersUsers)[] } = {
      Users: [
        {
          id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
          order: 1
        },
        {
          id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
          order: 2
        }
      ],
      UsersLogins: [
        {
          result: 1,
          UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
        },
        {
          result: 0,
          UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
        }
      ],
      UsersUsers: [
        {
          id: 1,
          order: 0
        },
        {
          id: 2,
          order: 0
        }
      ]
    };
    
    interface IPushedDataItem {
      data: IUser | IUsersLogin | IUsersUsers;
    }
    
    type TypePushedData = Array<IPushedDataItem>;
    
    let pushedData: TypePushedData = [];
    Object.keys(originalData).forEach(item => {
      const subItems = originalData[item];
      if (subItems) {
        for (const subItem of originalData[item]) {
          pushedData.push({
            data: subItem
          });
        }
      }
    });
    
    
    export interface IUser {
      id: string;
      order: number;
    }
    
    export interface IUsersLogin {
      result: number;
      UserId: string;
    }
    
    export interface IUsersUsers {
      id: number;
      order: number;
    }
    
    export interface IOriginalData {
      Users?: IUser[];
      UsersLogins?: IUsersLogin[];
      UsersUsers?: IUsersUsers[];
    }
    
    export type OriginalDataUnion = IUser | IUsersLogin | IUsersUsers;
    
    const originalData: IOriginalData & { [key in keyof IOriginalData]: OriginalDataUnion[] } = {
      Users: [
        {
          id: "e4e2bb46-c210-4a47-9e84-f45c789fcec1",
          order: 1
        },
        {
          id: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae",
          order: 2
        }
      ],
      UsersLogins: [
        {
          result: 1,
          UserId: "e4e2bb46-c210-4a47-9e84-f45c789fcec1"
        },
        {
          result: 0,
          UserId: "b95274c9-3d26-4ce3-98b2-77dce5bd7aae"
        }
      ],
      UsersUsers: [
        {
          id: 1,
          order: 0
        },
        {
          id: 2,
          order: 0
        }
      ]
    };
    
    interface IPushedDataItem {
      data: OriginalDataUnion;
    }
    
    type TypePushedData = Array<IPushedDataItem>;
    
    let pushedData: TypePushedData = [];
    for (const item of Object.keys(originalData) as (keyof IOriginalData)[]) {
      const subItems = originalData[item];
      if (subItems) {
        for (const subItem of subItems) {
          pushedData.push({
            data: subItem
          });
        }    
      }
    }
    
    导出接口IUser{
    id:字符串;
    顺序:编号;
    }
    导出接口IUsersLogin{
    结果:数量;
    UserId:string;
    }
    导出接口IUsersUsers{
    id:编号;
    顺序:编号;
    }
    原始数据导出接口{
    用户?:IUser[];
    UsersLogins?:IUsersLogin[];
    用户?:IUsersUsers[];
    }
    出口类型原始数据联盟=IUser | IUsersLogin | IUsersUsers;
    const originalData:IOriginalData&{[key in keyof IOriginalData]:OriginalDataUnion[]}={
    用户:[
    {
    id:“e4e2bb46-c210-4a47-9e84-f45c789fcec1”,
    订单:1
    },
    {
    id:“b95274c9-3d26-4ce3-98b2-77dce5bd7aae”,
    订单:2
    }
    ],
    用户斯洛金斯:[
    {
    结果:1,,
    用户标识:“e4e2bb46-c210-4a47-9e84-f45c789fcec1”
    },
    {
    结果:0,,
    用户标识:“b95274c9-3d26-4ce3-98b2-77dce5bd7aae”
    }
    ],
    用户用户:[
    {
    id:1,
    订单:0
    },
    {
    id:2,
    订单:0
    }
    ]
    };
    接口IPushedDataItem{
    数据:原始数据联盟;
    }
    键入TypePushedData=数组;
    让pushedData:TypePushedData=[];
    for(Object.keys(originalData)的常量项为(keyof IOriginalData)[]{
    常量子项=原始数据[项];
    若有(分项){
    用于(子项的常量子项){
    pushedData.push({
    数据:分项
    });
    }    
    }
    }
    
    让我们稍微简化一下您的示例:

    export interface A { s: string }
    export interface B { n: number }
    export interface C { b: boolean }
    
    export interface All {
        A: A;
        B: B;
        C: C;
    }
    
    //
    
    let all: All = {
        A: {s: "s"},
        B: {n: 33},
        C: {b: true},
    };
    
    let other: Array<A | B | C> = [];
    
    将失败,因为
    Object.keys
    被推断为
    Array
    ,而不是人们所期望的
    Array
    。看看为什么

    然而,同样的评论说,当使用泛型时,obj中k的
    推断
    k
    keyof
    。我们可以用它来编写自己的严格版本的
    对象

    function strictKeys<T>(o: T): Array<keyof T> {
        let a = [];
        for (let k in o)
            a.push(k);
        return a;
    }
    
    计算正确


    您希望推送的数据包含什么?你给它的类型签名说它希望对象具有
    数据
    属性,但你的代码没有这样做……我不认为盲目地添加
    [key:string]
    是个好主意。假设我们将
    Users:
    误键入为
    Userz:
    ——使用您的键入,TS将很高兴地允许这样做。是的,如果您还计划使用显式键而不是
    Object.keys提供的数据。添加了一个示例,该示例在keyof
    语法中使用了
    ,但它需要一个显式的cast@georg,我同意你的看法:使用
    [n:string]
    (或
    [key:string]
    )将允许在
    原始数据处出现错误的键,例如,
    错误:[{id:“e4e2bb46-c210-4a47-9e84-f45c789fcec1”,顺序:1}]
    。我不喜欢使用这个定制的
    strictKeys
    ,但是解释很好。谢谢
    strictKeys(all).forEach(k => other.push(all[k]))