2

I’m struggling to understand why this example isn’t considered valid by the typescript compiler:

interface IExample<T> {
  param: T
}

function testFunc<U, I extends IExample<U>>(myParam: U): I {
  return { param: myParam };
}

The error produced is:

Type 'U' is not assignable to type 'I["param"]'.

My (assumedly incorrect) reading of this snippet is:

  • IExample<T> expects param to have type T.
  • I is a subtype of IExample<U>, meaning param has type U.
  • myParam has type U from the parameter annotation.
  • Therefore myParam should be a valid value for param of I.

Prefixing the return value with <I> clears the error, so why does the error appear in the first place?

2
  • 1
    I would have expected a different error message: something like { param: U } isn't assignable to generic type I: I is an unknown type, which could have many more attributes and methods than just param. So { param: myParam } is almost guaranteed to not be of type I. Commented Nov 12, 2018 at 17:38
  • Found a duplicate which I missed before posting: stackoverflow.com/q/40690797/1813169 Commented Nov 12, 2018 at 17:54

1 Answer 1

1

The problem is that I might have other required properties in addition to param. Typescript will force your generic function implementation to return a valid value for any I that satisfies the constraint of extending IExample<U>, and it does not.

For example:

interface DerivedIExample extends IExample<number> {
  other : string
} 
let o = testFunc<number, DerivedIExample>(0)
o.other // required by the DerivedIExample but not assigned

In your simple example, it would be best to do away with I completely:

function testFunc<U>(myParam: U): IExample<U> {
  return { param: myParam };
}

You can force the compiler to accept your code using a type assertion but as outlined above that is not type-safe:

function testFunc<U, I extends IExample<U>>(myParam: U): I {
  return { param: myParam } as I; // NOT TYPE SAFE! USE WITH CARE !
}
Sign up to request clarification or add additional context in comments.

2 Comments

I don’t know why I didn’t just eliminate I in the first place, thanks! Is it worth opening an issue to note the unhelpful(/misleading?) error message?
It turns out the error has already been fixed in the nightly builds, it’s now: Type '{ param: U; }' is not assignable to type 'I'.

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.