Javascript 在TypeScript中键入对象数组
使用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
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]))