0

I have compilation error when I try the following syntax, but I don't understand why it does not work:

interface Param<O> {
    obj: O;
}
interface Dico {
    [key: string]: <O>(param: Param<O>) => Param<O>;
}
var x: Dico = {
    fnString: (param: Param<string>) => { return param; },
    fnNumber: (param: Param<number>) => { return param; }
};

Here is the playground link

Compilation error is on fnString and fnNumber:

Type '(param: Param<string>) => Param<string>' is not assignable to type '<O>(param: Param<O>) => Param<O>'.
  Types of parameters 'param' and 'param' are incompatible.
    Type 'Param<O>' is not assignable to type 'Param<string>'.
      Type 'O' is not assignable to type 'string'.  

If I move the generic type O on interface Dico, it works but I cannot use different types like I would like:

enter image description here

What I am missing ? Is this a limitation I can't go around or is there a way to achieve this?

2
  • Could you describe in more detail what you would like to achieve? What you've described is perfectly normal situation. In the former case Dico has values with generic functions accepting different Param<T> or the latter where all values of Dico<T2> accept Param<T2>. Commented Feb 24, 2019 at 7:53
  • I'm trying to achieve the first case, a type index (no generic) with generic functions as value. The need behind is to propose an interface that others developers can implement with methods that respect a "pattern" in order to consume them in my code. Commented Feb 24, 2019 at 8:51

1 Answer 1

2

The function you define as the rerun of the index is a geneic function. A generic function has its type argument decided by the caller not by the implentation, so only a generic function can be compatible with a generic function signature.

What you want is a non generic function coulpled with a way to enforce the relationship between input and output. You can do this using an extra function to help with the inference :

interface Param<O> {
    obj: O;
}

type Dico < T > ={
    [K in keyof T]: (param: Param<T[K]>) => Param<T[K]>;
}

function createDisco<T>(o: Dico<T>) {
    return o;
}
var x = createDisco({
    fnString: (param: Param<string>) => { return param; },
    fnNumber: (param: Param<number>) => { return param; }
    fnNumberErr: (param: Param<number>) => { return null as Param<string>; }
})
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that is exactly what I was looking for !
As mentioned by @Titian if it's for a param that's not an object with property type, it's just Dico, createDisco and calling that createDisco function without the Param wrapping the type in all cases.

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.