Skip to content

Refining discriminated union of arrays with array.find on a property that is a union #60785

Closed
@elusiveunit

Description

@elusiveunit

🔎 Search Terms

"discriminated union", "refine union", "array find union property"

🕗 Version & Regression Information

Tried every TypeScript version from 5.2.2 in the playground with the same result.

I found some similar issues that eventually led me to #42384, but I wasn't sure if the root cause is the same?

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.0-dev.20241217#code/JYOwLgpgTgZghgYwgAgMoAs5QA7IN4BQAkAPQnIBKEAtgPYBuoA5sgOQAqUwcITANhFbJ00FGFrImEMMi4ATZLRjIwI5AFcQwWiGTU4AawgBnZMBkB3WlAMA6YmACe2CAC42qAI7qsg5AB82Tm5eAVYAbmIEaxBoY3cQdWoAI2hIgF8CUEhYRBQKWk0FQiInF3dWAGFgKAQwgLYAeXo4PgjiKDg5YHV45ESUtIJMghhNBDBtXSkwSpi4gApjTBc+jCxsAG0AXQaCop2ASnxiMmQAUQAPFwmIBQADdZwGoogYUDv75GT1GSZaGSPTDPQL7EAKQKvd6xOT3KI6YwyGCFcFPXAAXmQyzgq1s0LkCyWKwgx3RAD4scTbGUUOi6R5vL5WIdIqRyAAFKC0FxQJxsaJQWJQYxCOS0Ez9AHICCXYCIxS6GkeYG4UEouSsexs5A6znc6B81gCoUi5BiiUgKUyuUyHQqZwoVhgjW2ZALABMAGZPQBOQ4daTqQXIZFFNEAflsxriGSAA

💻 Code

interface Sharp {
	// Removing 'Triangle' here to get rid of the union makes it work.
	type: 'Square' | 'Triangle';
	corners: number;
}
interface Round {
	type: 'Circle' | 'Oval';
	radius: number;
}

function getCorners(shapes: Sharp[] | Round[]) {
	// Expected `Sharp | undefined` but got `Sharp | Round | undefined`
	const foundSharp = shapes.find((shape) => shape.type === 'Square');
	// Property 'corners' does not exist on type 'Sharp | Round'.
	//   Property 'corners' does not exist on type 'Round'. (2339)
	return foundSharp?.corners;
}

🙁 Actual behavior

foundSharp is Sharp | Round | undefined even though it can never be Round due to type.

🙂 Expected behavior

foundSharp should be Sharp | undefined since only sharp shapes can have the type 'Square'.

Additional information about the issue

Setting type in the Sharp interface to only 'Square' makes it work as expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions