Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not narrowing nested discriminated union #42548

Closed
jonhue opened this issue Jan 29, 2021 · 2 comments
Closed

Not narrowing nested discriminated union #42548

jonhue opened this issue Jan 29, 2021 · 2 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@jonhue
Copy link
Contributor

jonhue commented Jan 29, 2021

Bug Report

🔎 Search Terms

nested discriminated union

This issue is definitely related to #18758, but it is different from that issue in that the tag is also present in the top-level type.
As in the top-level type, the nested types form a generic union, I believe this is also related to #13995.

🕗 Version & Regression Information

This is the behavior in every version I tried.

⏯ Playground Link

Playground link with relevant code

💻 Code

enum Kind {
	A,
	B,
}

type InnerA = {
	kind: typeof Kind.A
}
type InnerB = {
	kind: typeof Kind.B
}

type Inner = InnerA | InnerB

type Outer<T extends Inner = Inner> = {
	kind: T['kind']
	inner: T
}

const handleInnerA = (inner: InnerA) => {}
const handleInnerB = (inner: InnerB) => {}

const fn = (outer: Outer) => {
	switch (outer.kind) {
		case Kind.A:
			return handleInnerA(outer.inner)
		case Kind.B:
			return handleInnerB(outer.inner)
	}
}

🙁 Actual behavior

The above code should compile without errors.

🙂 Expected behavior

The type of the inner property on outer should be narrowed based on the value of outer's kind property.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jan 29, 2021
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jan 29, 2021

This is a correct error. Narrowing here would be unsound because this is a legal call:

const p: Outer = { kind: Kind.A, inner: { kind: Kind.B } };
fn(p);

See also #27808

@jonhue
Copy link
Contributor Author

jonhue commented Jan 30, 2021

oh yes, thanks! you're absolutely right

@jonhue jonhue closed this as completed Jan 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

2 participants