0

I want to sort of dynamically create an instance of an interface that has a key that is specified dynamically, through a function parameter

effectively I want to do something simple like this:

function callWith(key, value) {
   return fnWithKeyValue => 
     fnWithKeyValue({ [key]: value });
}

(What I specifically want this for is a React HOC with the ability to set a dynamic property, but I've tried to simplify above)

For instance, lets say I there is some function more or less beyond my control:

interface ValueType {
  magicValue: number;
}

function MyCallback(v: ValueType) {

}

And so I want this to successfully compile:

callWith('magicValue', 123)(MyCallback);

but I want this to fail to compile:

callWith('normalValue', 123)(MyCallback);

Is this even possible with TypeScript?

2
  • Why not just pass the object directly to MyCallback and do the check inside it? Commented May 19, 2018 at 0:12
  • This example maybe simplifies it too much - I'm trying to generalize this so that it accepts any MyCallback as a parameter, and I want the type signatures to match. Commented May 19, 2018 at 0:15

1 Answer 1

1

How about something like this:

function callWith<K extends string, V>(key: K, value: V): <R>(f: (a: Record<K, V>) => R) => R {
   return fnWithKeyValue => 
     fnWithKeyValue({ [key]: value } as Record<K, V>); // Note the cast here, I don't know of a way to avoid it.
}

It's a little tricky, since we've got a generic function callWith, that returns yet another generic function. But all it says is that the function you give as an argument to the function returned by callWith must accept the right type of object as it's parameter, specifically a Record<K, V>.

But, despite it's complex signature, it does seem to meet your requirements. The first example will compile without issue, but the second will create an error since MyCallback accepts an object with "magicValue" and not "normalValue":

interface ValueType {
  magicValue: number;
}

function MyCallback(v: ValueType) {}

callWith('magicValue', 123)(MyCallback); // OK
callWith('normalValue', 123)(MyCallback); // Error: Property 'magicValue' is missing in type 'Record<"normalValue", number>'
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.