Reputation: 25
I was trying to extract some properties from an object.
The keys which should be extracted are given as parameter to the function.
For example, for this code, it copies the specific keys from the object and returns new, another object with the same keys.
function pick(source: object, ...keys: string[]) {
const returnValue = {}
for (const key in source) {
const index = keys.indexOf(key)
if (index < 0) continue
keys.splice(index, 1)
returnValue[ key ] = source[ key ]
}
return returnValue
}
When I use this function, TypeScript infers the return type as {}
which is an empty object. Is there a way I can get this as { [key: .. in parameter 'keys' ..]: any }
?
I tried this but it did not work.
function pick<O>(source: object, ...keys: (keyof O)[]): O {
const returnValue: O = {}
for (const key in source) {
const index = keys.indexOf(key)
if (index < 0) continue
keys.splice(index, 1)
returnValue[ key ] = source[ key ]
}
return returnValue
}
Thank You
Upvotes: 2
Views: 16728
Reputation: 1299
If you want to "parse" two objects using same key, you should use Object.keys
let's assume you have two objects myObject and myOtherObj, if the keys are the same just use only one mapper :
Object.keys(myObject).map((key) => {
console.log(key) // should be the same for both obj
// your two obj values
console.log(myObject[key]);
console.log(myOtherObj[key]);
});
EDIT : you can also do Object.keys(myOtherObj).map....
Upvotes: 0
Reputation: 51629
There is built-in Pick type that was added in TypeScript 2.1 exactly for describing such a function:
function pick<T, K extends keyof T>(source: T, ...keys: K[]): Pick<T, K> {
Just for reference, it's a very simple mapped type defined as
type Pick<T, K extends keyof T> = {[k in K]: T[k]};
However, your implementation does not compile without type casts because TypeScript complains about keys.indexOf(key)
- key
is now keyof T
and it's not compatible with the type of indexOf
parameter, which is keys
element type - K
.
So I made slightly different implementation with a loop that goes over keys
array. I do not remove "used" keys from keys
- if there are duplicates (which is not likely I suppose), assigning the same value twice will do no harm here:
function pick<T, K extends keyof T>(source: T, ...keys: K[]): Pick<T, K> {
const returnValue = {} as Pick<T, K>;
keys.forEach(k => {
returnValue[k] = source[k];
});
return returnValue;
}
Upvotes: 2
Reputation: 1513
I think you can do a simple mapper between your objects:
interface OriginalObject {
property1: string
property2: string
property3: string
}
interface MappedObject {
mappedProperty1: string,
mappedProperty2: string
}
class Mapper {
static mapOriginalObjectToMappedObject(object: OrginalObject): MappedObject {
return {
mappedProperty1: object.property2,
mappedProperty2: object.property3
}
}
static mapFooToBaz ...
static mapBarToFoo ...
}
In your code:
const objectA: OriginalObject = {
property1: "foo",
property2: "bar",
property3: "baz"
}
const mappedObjectA = Mapper.mapOriginalObjectToMappedObject(objectA)
With this way, your code stay simple
Upvotes: 0