question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Union types are not expanded properly when checking if type satisfies generic constraint

See original GitHub issue

Bug Report

🔎 Search Terms

Union types expansion, generic constraints

🕗 Version & Regression Information

4.6, works fine in 4.5

⏯ Playground Link

Playground link with relevant code

💻 Code

type UnionType = {name: 'A'} | {name: 'B'}
type NotUnionType = {name: 'A' | 'B'}

type MyType<T extends UnionType> = number
// Errors here, because NotUnionType is presumably not assignable to UnionType
let d: MyType<NotUnionType>

// No error, because NotUnionType is assignable to UnionType
let check: NotUnionType extends UnionType ? true : false 
    = true

The error doesn’t reproduce, however, if I change the order of lines:

let check: NotUnionType extends UnionType ? true : false 
    = true
// No error
let d: MyType<NotUnionType>

🙁 Actual behavior

Error when instanciating MyType<NotUnionType>

🙂 Expected behavior

No error. Also error trace seems to be missing some entries in the beginning (I would expect it to start with something like NotUnionType does not satisfy the constraint UnionType whereas in actuality is starts with Type 'NotUnionType' is not assignable to type '{ name: "B"; }').

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:3
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
fatcerberuscommented, Jul 5, 2022

In that case, repro:

type AObjOrBObj = { name: "A" } | { name: "B" };
type AOrBObj = { name: "A" | "B" };
type Generic<T extends AObjOrBObj> = T;

type T = Generic<AOrBObj>;  // error if here

declare let x: AObjOrBObj;
declare let y: AOrBObj;
x = y;  // ok
y = x;  // also ok

//type T = Generic<AOrBObj>;  // not an error if here
1reaction
fatcerberuscommented, Jul 5, 2022

This looks like two bugs, actually:

  1. What seems like a caching bug, as you note
  2. NotUnionType extends UnionType should not be true. In general { x: T | U } is not assignable to { x: T } | { x: U } (but the inverse is okay), and extends in this context means “is assignable to”

edit: I stand corrected on point 2. See Ryan’s comment immediately below.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Extending Union Types Alias in TypeScript? - Stack Overflow
I think you're using the word "extendable" in a different sense from what the keyword extends means. By saying the type is "extendable" ......
Read more >
Frequently Asked Questions (FAQ)
How are generics implemented in Go? How do generics in Go compare to generics in other languages? Why does Go use square brackets...
Read more >
Constraints on type parameters - C# Programming Guide
The type argument must be a non-nullable type. The argument can be a non-nullable reference type or a non-nullable value type.
Read more >
Empowering Union and Intersection Types with Integrated ...
that, so far, subtyping algorithms for type systems extended with union and ... for many uses of generic methods (though not all, since...
Read more >
Constrained genericity - Rosetta Code
Say a type is called "eatable" if you can call the function eat on it. ... The constraint is shown in the formal...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found