1

I am using the intl-ts library. The following function does not compile because it complains that lang[result] is not known to be executable:

function convertResult<
  T extends Messages &
    { [P in K]: (fieldName: string, p1: P1, p2: P2, p3: P3, p4: P4) => string },
  K extends keyof T,
  P1 = any,
  P2 = any,
  P3 = any,
  P4 = any
>(
  result: K | null,
  params: [P1, P2, P3, P4],
  lang?: Intl<T>,
  fieldName?: string
): boolean | string | null {
  if (result === null) {
    return lang ? null : true
  } else {
    if (lang) {
      return lang[result](fieldName, ...params)
    } else {
      return false
    }
  }
}

I believed that the definition of K (type of result) would be enough for the compiler to know that lang[result] is indeed a method which takes the appropriate parameters.

So, I wonder if the problem is:

  • something I missed in this code.
  • something I missed in intl-ts (I am the maintainer of this package).
  • or something too complex for Typescript and maybe I should open an issue for it.

A simple example is provided here

4
  • Could you setup simple example in playground to reproduce the problem? Commented Sep 21, 2018 at 8:48
  • The Messages & is the part that is causing problems. What does that interface contain ? Commented Sep 21, 2018 at 9:08
  • @TitianCernicova-Dragomir Please look at Messages source code Commented Sep 21, 2018 at 9:15
  • @AlekseyL. I edited the question to add a link to playground example. Commented Sep 21, 2018 at 9:23

1 Answer 1

2

The problem is cause because of the intersection with Messages. Typescript will not properly infer the corect type for the index access because of it.

In this particular case I would just remove the intersection. Don't think it servers a major role, it just restates that T must contain function or strings, the mapped type you use to constrain T is much more restrictive, so if an object conforms to the constraint of T it will conform to Messgaes,

function convertResult<
    T extends { [P in K]: (fieldName: string, p1: P1, p2: P2, p3: P3, p4: P4) => string },
    K extends keyof T,
    P1 = any,
    P2 = any,
    P3 = any,
    P4 = any
    >(
        result: K | null,
        params: [P1, P2, P3, P4],
        lang?: T,
        fieldName?: string
    ): boolean | string | null {
    if (result === null) {
        return lang ? null : true
    } else {
        if (lang) {
            return lang[result](fieldName, ...params)
        } else {
            return false
        }
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This works well by both removing Messages and modifying lang to directly be of type T. Anyway, I would say it is a bug in Typescript compiler and requires an issue. Do you think the same?
@StéphaneVeyret I think it's a bit more complicated.. there are lots of problems when you want to go from generics to concrete types inside a function .. I would have expected it work, but I expect a lot of things to work and they don't always work because of other constraints. I definitely think it's work a github issue to get an official possition
I'll open an issue then, and let the team decide if it should be corrected or not. Thank you.

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.