Typescript generic interface parameter assignment

Viewed 284

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?

1 Answers

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 !
}
Related