I'm trying to create a type to describe an ES6 Proxy object where I will know the types for a few keys, and the rest of the keys will be generic with a callback as a value and I won't know their names until runtime.
However, if I try something like this:
interface MyCallback {
(): void;
}
interface MyType {
myKey1: number;
[key: string]: MyCallBack;
}
I get errors like:
[ts] Property 'myKey1' of type 'number' is not assignable to string index type 'MyCallback'.
If I add [key: string]: number
, I get the error Duplicate string index signature
.
If I overload it so it's like number | MyCallback
, I get this error if I try to call a callback on a MyType
instance:
[ts] Cannot invoke an expression whose type lacks a call signature. Type 'number | MyCallback' has no compatible call signatures.
Is it possible to have a type like I'm trying to create in TypeScript?
the answer is sort of. You can accomplish this with intersection types:
interface MyType {
myKey1: number;
}
interface MyCallBack {
(): void;
}
interface GenericCallbackType {
[key: string]: MyCallBack;
}
type CombinedType = MyType & GenericCallbackType;
const obj: CombinedType = {
myKey1: 8,
anyString: () => {}
}
As noted in comments the accepted answer doesn't work with assignments, resulting in a Property 'myKey1' is incompatible with index signature
error. To work with assignments we can utilize @jcalz's answer here:
interface MyCallback {
(): void
}
interface MyType {
myKey1: number
}
const asCombinedType = <C>(
res: C & MyType & Record<Exclude<keyof C, keyof MyType>, MyCallback>
): C => res
const obj = asCombinedType({
anyKey: () => { /* ...*/ },
myKey1: 12
})
Admittedly a bit convoluted but it gets the job done.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With