Reputation: 2942
If i have an object as such
let obj = {
property1:()=>{ return Date()} // eg it doesn't have to be a date
property2:()=>{ return 1}
}
Now i want to transform this to type
{
property1:Date,
property2:number
}
How would i go about defining this in typescript. Just about everything i end up doing just does get it right.
I know the properties so i know it's something like
type Transform<T> = Record<keyof T,?>
how do i get each individual property to be transformed so that the final object can be typed as well.
//Some may need a little bit more solid example
Lets say this is a react app.
let dependencies = {user:UserContext}:{[key:string]:React.Context<any>}
Now i can transform all of my react context to the actual instances inside the context using something like
Object.entries(contextObject).map(([key,context])=>{
return {[key]:useContext(context)}
}).reduce((a,b)=>{
return {...a,...b}
},{})
This object will be all of the properties transformed.
I take in a config object of sorts and transform the properties keeping everything the same,
This can be anything, converting some parameters to db tables, converting dependencies to add to a class, without actually having to create the instance
Doing it isn't hard, it's having it typed so that on the other end of the transformation, i know what the type of object has been transformed into.
Upvotes: 1
Views: 60
Reputation: 25800
Use the built-in Record
and ReturnType
types:
/**
* Apply the constraint of having functions as values.
*/
type Source = Record<string, () => any>;
/**
* Map functions to their return types.
*/
type Transform<T extends Source> = {
[Property in keyof T]: ReturnType<T[Property]>
}
/**
* Make sure the argument fulfills the requirement.
*/
declare function transform<T extends Source>(source: T): Transform<T>;
Usage:
let source = {
property1: () => { return new Date() },
property2: () => { return 1 }
}
/**
* `property1` is an instance of `Date`, property2 is a `number`.
*/
const { property1, property2 } = transform(source);
The transform
function can be implemented this way:
function transform<T extends Source>(source: T): Transform<T> {
return Object
.entries(source)
.reduce(
(cumulus, [key, value]) => Object.assign(cumulus, { [key]: value() }),
Object.create({}),
);
}
Upvotes: 3