Typescript: Type of Action Parameter in Union #2150
-
Bug report
Also, I've asked this as a question on stackoverflow. Sandbox link or minimal reproduction code const Foo = types.model({
id: types.identifier,
payload: types.maybe(types.string),
}).actions((self) => ({
updatePayload(payload?: string) {
self.payload = payload;
},
}));
const Bar = types.model({
id: types.identifier,
payload: types.array(types.array(types.boolean)),
}).actions((self) => ({
updatePayload(payload: boolean[][]) {
applySnapshot(self.payload, payload);
},
}));
const Item = types.union(Foo, Bar);
const Bucket = types.model({
items: types.map(Item),
}).actions((self) => ({
updateItemPayload(id: string, payload?: string | boolean[][]) {
const item = self.items.get(id);
item && item.updatePayload(payload);
},
})); Describe the expected behavior Describe the observed behavior |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments
-
Hey @chriszwickerocteris - I'm sorry no one ever got back to you here. We are trying to revamp the MST repository, and TypeScript issues are definitely on our radar. I'm going to tag this as such. If this issue is still relevant to you and you're interested in helping, let me know. But I totally understand if it's just not a priority for ya anymore. Thanks! |
Beta Was this translation helpful? Give feedback.
-
Hi @coolsoftwaretyler - we finally moved away from MST, so at least for now, this isn't an issue for me any longer. Thanks anyway ;-) |
Beta Was this translation helpful? Give feedback.
-
Thanks for the follow up @chriszwickerocteris, sorry it didn't work out for ya. We'll leave the issue open as we work to revamp everything |
Beta Was this translation helpful? Give feedback.
-
Since I've been picking up some of the TS work, I can pitch in. Both MST and TS are doing the right thing. In type F = ((payload: boolean[][]) => void) | ((payload: string) => void) It doesn't know which of those two the function is, so what happens if we give Given your example, you'd unfortunately have to narrow both the argument and the function to make TS happy, like this: if (Foo.is(item) && typeof payload == "string") {
item.updatePayload(payload);
} else if (Bar.is(item) && Array.isArray(payload)) {
item.updatePayload(payload);
} else {
const type = getType(item);
throw new Error(`Item type ${type.name} can't process payloads of type ${typeof payload}`);
} Hope this helps! (and given this, I think we can close the issue?) |
Beta Was this translation helpful? Give feedback.
-
Thanks @thegedge - that's very helpful. I'm going to convert this to a discussion, which will close the issue. Then I'll mark your answer as "the" answer. Really appreciate your time, and your TS expertise. |
Beta Was this translation helpful? Give feedback.
Since I've been picking up some of the TS work, I can pitch in.
Both MST and TS are doing the right thing. In
updateItemPayload
,item.updatePayload
is going to be of this type:It doesn't know which of those two the function is, so what happens if we give
F
astring
and the underlying instance is actually the function that takes aboolean[][]
? That's why you're seeingboolean[][] & string
, because if the payload you're providing is both possible types at the same time, it'll work for all members of the union. A simplified version of this in the TS playground:Given your example, you'd unfortunately have to narrow bot…