union errors are proportional to the number of elements. As a simple example:
````js
type Action =
| { type: 'A', payload: number }
| { type: 'B', payload: string }
| { type: 'C', payload: boolean }
| { type: 'D', payload: number };
function reducer(action: Action) {
if (action.type === 'E') {
// const b: number = action.payload;
}
}
````
This can get somewhat unwieldy when the union is large (50, 100 elements), however the error line is in the correct spot from the IDE.

A larger example: https://flow.org/try/#0C4TwDgpgBAggxsAlgewHZQLwCgpQD5QDeUokAXFAOQyUA0UYAhiADbKMAmFqArgLYAjCACcoAXxz4iJcBAqUAQnQbM2nCgGdgwxKgDm4yQWKk5VAMLKmrdlygDkyFhEboJuYzPJUAIldW23PxCou5SJrLyAKL+NupQvIIihh7SpvIAYrFqdokhKeFeZpQA4tmBCcHJYZ7pVAAS5fFaOvoFtZFUAJJNdg5OLm5GaZ2UAFK9QUmhwxHelADSk5XT7SPzADLLedWzRfIAsttVM6lzxQByyy26BjXrxQDyy-3Ormvn8gAKx6v3n1QAIq-fL-fZUABKIN2Z3BlAAytDToU6pQACrXbS3D5wgCqL0cbyGsNRADUkTjUQB1Clg1EADVpe1RICZJNGMBo9GsOSmoOZowUSm5AWaWLadNG5ksIrifUJg0pox8fllvJW-PZ8yiMTVFR2yI68wyWT18QNSvmJTKZtyJ0txXqjVtmnFdwF8y6PRd9gV70l8zGEx9FoDxQWSxD9rD8g2Wyjfw9xQORwTmpRowuVx9NwlSfkj2ePteipjVC+PzTMIz80BwKrhoe8ghUIbDvk8MRbbL6IxObd7aouPxxb9xJrxVJ5O7+aoVJpM61xXpjMXE-kIFZM9n1E5XJUcr51aNxSFQsxrXdS-k0ulBIG-p3KpVbPXVB1OtfJ8yJtNB-VoY7ta1pfk2DROs6-4VLmV5vpQXpeveRKDuMQbBlB5rRjuEYRqBAKUHGcZ4XCKYpsRqJZlmF7Yj2haFkhpY7hWFbkaMdZ1qx8wti2nHFJ2na8fIaLCX2GF2DBKHDsODGPteVBTlOglzvOC5iUejb4SuK5KZQm6bjpe6GfuPL6lhcmKGelnUXm5m3nZMpqb6D7jt+vjPu5Okfl5uqOYB5m-gFf4mZhibmcB4U2r5ZlwRBsWQcF4kDj2CEpd6jklrJcFodl6EJepKE4YVkZRaFcGEeV8YlemrmUKRdWplVx5gZQlGtdmjkSbRdHdTJLnNcxA2Vo1GlwuxY31sNKHcdNraTT2-ELV2c07iJq2iXlUCdTuUk7SO6VjihClHdOy3mSp52qRtflwVpt2rqdcF6U9W7LVgABmPCoAgKDoMIEAcDwcAiAAFIw31oBQ8BIGgACURCSIgb1QKD4OoAAdKYmAYBgVAAFr47jlBw4Qki4AA9GTUBwGgWj2PlONg9D6MJQA3JIEhiEAA
The errors are verbose by design. There's no need to provide such a large union of so many possible payload shapes. That's almost akin to typing JSON.stringify() with a shape of every possible object.
A simple shape definition should suffice:
type Action = {
type: string,
[string]: any
}
@lxe that's not type safe. you won't get errors when actions change, for example, in invalid ways that break other apps.
@lxe
Here's an example of the motivation to type actions (beyond just any) https://flow.org/try/#0C4TwDgpgBAggxsAlgewHZQLxQN4CgpSiQBcUAzsAE6KoDmANPlANoXV0C6pAhqiLgF9cwuGgpRupeEjSYchcBFIByGMvpQw3EABtk3ACakAjAAYoAgNy5RqcQCMpCFOizYFJKMoBC6zdr1DFQB3ZGDlC2thADMAV1RnWWjkZAAKbkTUJxlUAEocfERoqHTMgDoiaAxqrzV8vAIoSghgWMp0DJzrC0Li0pyKxUwan2V6pihbcWBkYG4dOW4yrV19AygAKigAJksoAHp9iWWAtahEMnIqGloAQmOVwPWt7fPLgDleW9uJ5tb2iSZbpCc59TouQaQYZYZQAYTGBUafzaHSBE0OUHeyCgEEolGQlDIGggADcIOhgAALZCxWiUqCwqAGZAQMioZTAHEADwuwDKhEpF0myAM0GCiB0C1QpNxUHs0Dg8x0EAMZXwIORAPBaGsAiAA
This is a good case for simply checking instance types:
class Action {
// Might as well be object, but this is ok too...
}
class MyNumberAction extends Action {
payload: number = 10;
}
class MyStringAction extends Action {
payload: string = 'wow';
}
function foo(action: Action) {
if (action instanceof MyStringAction) {
return action.payload * 2 // should throw error
}
}
Will throw very succinct errors:
15: return action.payload * 2 // should throw error
^ Cannot perform arithmetic operation because string [1] is not a number.
References:
10: payload: string = 'wow';
^ [1]
Likewise, foo(notAction) throws:
foo({})
19: foo({})
^ Cannot call `foo` with object literal bound to `action` because object literal [1] is incompatible with `Action` [2].
References:
19: foo({})
^ [1]
13: function foo(action: Action) {
^ [2]
@lxe Worth considering. With that said, the class approach requires us to rewrite a lot of our code, is a lot more verbose and requires lots of unneeded import statements for the class. Apologies but do you mind if we keep the thread on topic to the original issue?
If you already wrote code in which you create unions of hundreds of various object shapes, you should probably rewrite it anyways.
@lxe why is that?
Because union errors are verbose for large unions.
@lxe that's the point of this issue. Fixing the error message output would eliminate all disadvantages to action unions.
for those interested, here's a little short jq script you can use to shorten the error messages, if you'd like: "flow-less": "node node_modules/.bin/flow status --json | jq -r '[ .errors[].message[0] | (.path + \":\" + (.line | tostring)) + \"\\n Context: \" + .context + \"\\n Limited description: \" + (.descr | .[0:100]) ] | \"Error at \\(.[])\\n\"'",
Large unions often have a type alias. It would be nice if we just pointed to the type alias instead of pointing to each case in the union.
Most helpful comment
Large unions often have a type alias. It would be nice if we just pointed to the type alias instead of pointing to each case in the union.