1

Why is my SupposedId type below not a type identity?

Typescript is complaining that Type 'T' is not assignable to type 'SupposedId<T>'.

How comes T cannot be assignable to either T or T, what am I missing?

type SupposedId<T> = T extends object ? T : T;

function makeId<T>(test: T): SupposedId<T> {
  return test // <- Type 'T' is not assignable to type 'SupposedId<T>'
}

Playground example

5
  • 1
    That's interesting. But what's the point of SupposedId? I'm not asking to dismiss the issue (which is definitely interesting), but it may help us understand your end goal. Commented Jan 23, 2023 at 14:42
  • The type definition for SupposedId<T> is not correctly defining a type identity. It is saying that if T extends object, then SupposedId<T> is equal to T, otherwise it's equal to T. Since all types extend object, T will always be assignable to T, but not to SupposedId<T>. You should change your definition to: type SupposedId<T> = T; This way, SupposedId<T> will be the exact same type as T and the function makeId will work as expected. Commented Jan 23, 2023 at 14:45
  • 1
    Thanks all, @T.J.Crowder I want to work on one of the branches of the condition, and I just boiled the issue down to this. Commented Jan 23, 2023 at 14:48
  • 1
    @baggiogiacomo Not all types extend object - primitives such as string, number, and bool are not objects. Commented Jan 23, 2023 at 14:49
  • @baggiogiacomo - Example Commented Jan 23, 2023 at 14:57

1 Answer 1

5

This is because of distributed conditional types. SupposedId distributes to T extends any | T extends object. Yours is certainly a novel case, since they both actually resolve to T, but the conditional type performs different narrowing based on whether or not T extends object.

However, per the documentation, you can fix it by adding square brackets around each side of the extends keyword:

type SupposedId<T> = [T] extends [object] ? T : T;

function makeId<T>(test: T): SupposedId<T> {
  /* `test` is now one of `T extends object` or `T extends any`,
     not `T extends object | T extends any` */
  return test;
}
Sign up to request clarification or add additional context in comments.

Comments

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.