英文:
Extract generic values from a known object
问题
我正在尝试构建一个接受两个对象的函数,一个对象我知道其类型,另一个对象将是通用的。是否可能从已知对象中提取通用属性?
我在这方面遇到了一些困难,但以下是我尝试过的内容:
interface IPerson {
name: string;
age: number;
height: number;
weight: number;
job: string;
}
interface IAgeAndJob {
age: number;
job: string;
}
interface IHeightAndWeight {
height: number;
weight: string;
}
const person: IPerson = {
name: 'Leon Kennedy',
age: 21,
height: 5.11,
weight: 165,
job: 'Police Officer'
};
const mapProperties = <IPerson, T>(person: IPerson): T => {
let obj = {
// 从 person 中提取存在的属性
} as T;
console.log(obj);
return obj;
};
const result = mapProperties<IPerson, IAgeAndJob>(person);
如果我使用已知类型来执行此操作,我只需使用 Object.keys
获取键并遍历 person 对象以获取所需内容。是否有一种方法可以做到这一点?
英文:
I'm attempting to build a function that accepts two objects, one object I know the type of, the other will be generic. Is it possible to extract the generic properties from the known object?
I've kind of hit a wall on this one, but here's what I've tried:
interface IPerson {
name: string;
age: number;
height: number;
weight: number;
job: string;
}
interface IAgeAndJob {
age: number;
job: string;
}
interface IHeightAndWeight {
height: number;
weight: string;
}
const person: IPerson = {
name: 'Leon Kennedy',
age: 21,
height: 5.11,
weight: 165,
job: 'Police Officer'
};
const mapProperties = <IPerson, T>(person: IPerson): T => {
let obj = {
// extract properties from person where they exist
} as T;
console.log(obj);
return obj;
};
const result = mapProperties<IPerson, IAgeAndJob>(person);
If I was doing this with a known type I would just grab the keys using Object.keys
and iterate over the person object and grab what I need. Is there a way of doing this?
答案1
得分: 2
你显示的方式无法精确执行此操作。为了理解原因,让我们看看如果没有类型信息会怎样:
const mapProperties = (person) => {
let obj = {
// 从 person 中提取属性(如果存在)
};
console.log(obj);
return obj;
};
问题在于:在运行时,没有有关要提取哪些属性的信息,因此无法编写运行时代码来提取它们。
最接近的方法是创建一个函数,在这个函数中告诉它要提取哪些属性:
const mapProperties = <ObjectType extends IPerson, Keys extends keyof IPerson>(
person: ObjectType,
keys: Keys[]
): Pick<ObjectType, Keys> => {
const obj: Partial<ObjectType> = {};
for (const key of keys) {
obj[key] = person[key];
}
return obj as Pick<ObjectType, Keys>;
};
const result = mapProperties(person, ["age", "job"]);
console.log(result);
我保留了对象类型的泛型,因为你使用了一个泛型类型参数,但如果这仅适用于 IPerson
,你可以删除 ObjectType
,直接使用 IPerson
:
const mapProperties = <Keys extends keyof IPerson>(
person: IPerson,
keys: Keys[]
): Pick<IPerson, Keys> => {
const obj: Partial<IPerson> = {};
for (const key of keys) {
obj[key] = person[key];
}
return obj as Pick<IPerson, Keys>;
};
这引发了一个问题:我们从哪里获取 [ "age", "job" ]
数组?
你无法从 IAgeAndJob
获取它,但你可以反过来,从一个共同的源获取 IAgeAndJob
和该数组,这个源就是一个模型对象:
const ageAndJobModel = {
age: 42,
job: "programmer",
};
type IAgeAndJob = typeof ageAndJobModel;
const ageAndJobKeys = Object.keys(ageAndJobModel) as (keyof IAgeAndJob)[];
// 在其他地方使用它
const result = mapProperties(person, ageAndJobKeys);
console.log(result);
英文:
You can't do it in exactly the way you've shown. To see why, let's look at what it would be without any types:
const mapProperties = (person) => {
let obj = {
// extract properties from person where they exist
};
console.log(obj);
return obj;
};
You see the problem: There's no runtime information about what properties you want to extract, so you can't write runtime code to extract them.
The closest you can come is a function where you tell it what properties you want:
const mapProperties = <ObjectType extends IPerson, Keys extends keyof IPerson>(
person: ObjectType,
keys: Keys[]
): Pick<ObjectType, Keys> => {
const obj: Partial<ObjectType> = {};
for (const key of keys) {
obj[key] = person[key];
}
return obj as Pick<ObjectType, Keys>;
};
const result = mapProperties(person, ["age", "job"]);
console.log(result);
I kept the object type generic because you'd used a generic type parameter, but if this is only for IPerson
, you can remove ObjectType
and just use IPerson
directly:
const mapProperties = <Keys extends keyof IPerson>(
person: IPerson,
keys: Keys[]
): Pick<IPerson, Keys> => {
const obj: Partial<IPerson> = {};
for (const key of keys) {
obj[key] = person[key];
}
return obj as Pick<IPerson, Keys>;
};
This begs the question: Where do we get the ["age", "job"]
array from?
You can't get it from IAgeAndJob
, but you can flip that on its head and get IAgeAndJob
and the array from a common source — a model object:
const ageAndJobModel = {
age: 42,
job: "programmer",
};
type IAgeAndJob = typeof ageAndJobModel;
const ageAndJobKeys = Object.keys(ageAndJobModel) as (keyof IAgeAndJob)[];
// Using it elsewhere
const result = mapProperties(person, ageAndJobKeys);
console.log(result);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论