0

Minimal code to reproduce the typescript error.

type OptionalExceptFor<T, TRequired extends keyof T> = Partial<T> &
  Pick<T, TRequired>;

function some<
  TTask extends { [id in TId]: string },
  TId extends keyof TTask
>(task: Pick<TTask, TId>): OptionalExceptFor<TTask, TId> {
  return task;
}

It might look insane, but I've removed everything that is not related to the error. The idea is:

  • TTask is any interface with some property that is considered as an identifier.
  • This property is passed to the generic as a type parameter, because for different TTask types this property may be different.
  • Identifier is expected to be a string.
  • The function gets an object that contains at least the identifier (in real scenario some other properties also, from the common ancestor of TTask - removed for simplicity).
  • The function returns an object that is guaranteed to have the identifier required, and it may have some other properties of TTask but they are optional. I'm using OptionalExceptFor from https://stackoverflow.com/a/52703444/3082178.

The error is

Type 'Pick<TTask, TId>' is not assignable to type 'OptionalExceptFor<TTask, TId>'.
  Type 'Pick<TTask, TId>' is not assignable to type 'Partial<TTask>'.
    Type 'keyof TTask' is not assignable to type 'TId'.
      'keyof TTask' is assignable to the constraint of type 'TId', but 'TId' could be instantiated with a different subtype of constraint 'string | number | symbol'.
        Type 'string | number | symbol' is not assignable to type 'TId'.
          'string | number | symbol' is assignable to the constraint of type 'TId', but 'TId' could be instantiated with a different subtype of constraint 'string | number | symbol'.
            Type 'string' is not assignable to type 'TId'.
              'string' is assignable to the constraint of type 'TId', but 'TId' could be instantiated with a different subtype of constraint 'string | number | symbol'.(2322)

Here is the Typescript playground.

I feel that the problem is caused by TId extends keyof TTask, but can’t think of any way to declare another way. Any suggestion would be appreciated.

AKd
  • 501
  • 4
  • 17
  • Can you show a call to the `some()` function? It looks like there's no way for the compiler to infer `TId` except as the full list of keys from `task`, which isn't your intent. Is someone supposed to manually specify the generics like `some<{a: string, b: number}, "a">(...)`? Or is the real code able to infer `TId` from another parameter you left out like `some({a: "", b: 1}, "a")`? The compiler's error message is reasonable because it can't be sure you don't do `some<{a:string,b:number}>(x)` where `x`'s type has a non-numeric `b` property. Not sure how to fix without understanding the use. – jcalz Aug 02 '20 at 15:27
  • See [this](https://www.typescriptlang.org/play/#code/C4TwDgpgBA8mwEsD2A7AhgGwKIA8DGE8AYkgE4A8AKgDRSUBKEAjgK4KkQAmUEOwEKTgGcoAawggkAMzoA+KAF4oABTSlEmKvIBkAKCgqEeUVVoNmbDp1kBuXbqksUeRKihCkAWwjl9dSmhCojx8AsJQAN5QANoI3AgodACSnAC6AFzuwKQJAOZQAL7UfpQpIfyCIuKSMpQBQbqyABTAgaKZykYmdW1mKbIAlJlwrujY+ITAJBQ9QX3WkX4cwCykia1BdgX2CfykUmgEUAAakVBomULZebQARpfXKPkFdnioV1A4madKURdQACIAXdMkDCq93sAoEgkGAREoPN5yH8HjkniCoCgWJ5bhBSIVaAC0ADmjgBnYYXCAHS3AD8VOASCICBwXCa5IMAHpOVBSE5EN4eKRSGQgA) for an example of the problem. – jcalz Aug 02 '20 at 15:30

0 Answers0