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

Error in value of union passed as argument to function that is a property of the same union #53606

Closed
lucasbasquerotto opened this issue Mar 31, 2023 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@lucasbasquerotto
Copy link

Bug Report

When a union of types is used as argument in a function, and you pass a property of this type as value to another property that is a function that expects the corresponding type, and the function itself may vary according to the initial union, but each possibility of the union can be correctly applied to the function, then an error occurs (simple demo below).

This can be avoided if you verify explicitly each possibility in the union, but this can cause a performance degradation (aside from boilerplate), as well as future issues with maintenance, because each call should be repeated, and when changing one call, all calls should be changed. This is even worse when calling functions or returning react components with several props, repeating the same props every time (there were times in which I forgot to change every case, causing bugs, thankfully not production bugs).

I see this problem ever since I started using typescript, and even in recent versions I don't see it addressed (I don't know if this is complex to solve). In any case, I gave a search in the FAQ and in the issues and haven't found one related to this issue specifically.

🔎 Search Terms

union
function

🕗 Version & Regression Information

Tested on 4.9.5 and Nightly (Playground)

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about "union"

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.1.0-dev.20230331#code/MYewdgzgLgBApmArgWxgFQJ4Ac4wN4BQAkGgJoAKAogPoCCMAvDAOQCGzANMWVdQEKMWAI04EAvgQJRsuek2gAnAJZgA5gG5J0nDAFMkyIXAWaCcAB5YQC2NtnAoS8LQDCCuKyjXBACiVQ4ZAAuGFoASkYAPlCHJzAASTAAMxBTCysbGDsYx3A+Nw8vBV9-QJC+CIZo2ljwRJS0y2tbGRy4gs9vJj8A4NCYAB9dSurahOTUyXTmmBUAhSTWYHtc8ZT8YiXVgH4QnxGYADcQJQATTSJ3Q+MoXZghEBAAGw8wTQkpVvIFECwIRmIQ0IRBBdhCmBwADoeDRaBcQaU+nDiCCtu13J0FHcaqtXBiioMYIgwKc4EkVHBzsQYDAJEQgSiiGD0DJoRQaHx4UREeUuWjwB0itixvl8d4hsTSeSwJSLjS6QyQUyZCFJWSKVSlTz+kNOYz+WBBdZhasjcUJST1TLNfLTKBILAAO7WADW-26eCyMg4s16PoNZtpIW+vwgB2B9ugMANvhGKOyDETLKhMLojO20bGZu2kJ6gTCjJCCaTELgbN4fHTmdNYqxucRBaVIQDtZzeeQYQu7igiAUYGrcXedvAUeMP2KHt9gX9WdrQZgIb+4eIkdgMe6BxbhWN9d6neI3d7-YNQ8kkeeZaeIFUPgAhLfnQo3T772PrPugA

💻 Code

const enum Type {
	TYPE_A = 'a',
	TYPE_B = 'b',
}

type A = string;

type B = number;

export type ActionACreator = (item: A) => ActionInfo;

export type ActionBCreator = (item: B) => ActionInfo;

export type ActionCreator = (item: A | B) => ActionInfo;

export interface ActionInfo {
	action?: () => void;
	revert?: boolean;
}

type Props =
	| {
			type: Type.TYPE_A;
			item: A;
			actionCreator?: ActionACreator | undefined;
	  }
	| {
			type: Type.TYPE_B;
			item: B;
			actionCreator?: ActionBCreator | undefined;
	  }
	| {
			type: undefined;
			item: A | B;
			actionCreator?: ActionCreator | undefined;
	  };

const works = ({ type, item, actionCreator }: Props) => {
	const action = () =>
		type === Type.TYPE_A
			? actionCreator?.(item)
			: type === Type.TYPE_B
			? actionCreator?.(item)
			: actionCreator?.(item);
	return action;
};

const error = ({ item, actionCreator }: Props) => {
	const action = () => actionCreator?.(item);
	return action;
};

console.log(!!works, !!error);

🙁 Actual behavior

It shows an error when each type in the union is not inspected.

🙂 Expected behavior

The error function should be considered correct because each possibility of the union respects the argument of the function (of the same type).

@fatcerberus
Copy link

fatcerberus commented Mar 31, 2023

TS doesn't really understand the higher-order concept that item (a union of values) is correlated with actionCreator (a union of functions) by way of Props. This would need something like #30581, I think.

edit: On second reading I think this is a straight-up duplicate of #30581

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 31, 2023
@lucasbasquerotto
Copy link
Author

@fatcerberus Thanks for pointing that issue, I searched but haven't found it. The term is correlated (if I used it I would have found it previously). I will close this issue and subscribe to that one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants