[BUG] Mapped type becomes undefined
miro-ku opened this issue · 11 comments
Hi there, I have some trouble using this library in my project. This was working in firelordjs@<=2.4
, don't know if it works in firelordjs@>=2.5
, didn't check yet
- Version?
2.4.15 - What is the Meta Type?
import type { MetaTypeCreator } from 'firelord';
type SomeObject = {
key: string;
};
type FirestoreDummyData = {
string: string; // ok
array: string[]; // ok
number: number; // ok
regular_object: {
test: string;
}; // ok
mapped_primitive: Record<string, string>; // becomes undefined
mapped_object: Record<string, SomeObject>; // becomes undefined too
};
export type DummyMetaType = MetaTypeCreator<FirestoreDummyData, 'Dummy'>;
const test: DummyMetaType['read'] = {
string: 'test', // ok
array: ['test'], // ok
number: 10, // ok
regular_object: { test: 'test' }, // ok
mapped_primitive: { // TS2322: Type '{ test: string; }' is not assignable to type 'undefined'.
test: 'test',
},
mapped_object: { // TS2322: Type '{ test: { key: string; }; }' is not assignable to type 'undefined'.
test: {
key: 'test',
},
},
};
- What operations are you trying to run?
I'm trying to use mapped object in meta type - What do you expect?
Mapped type should work as intended - What is actually happening?
Mapped type becomes undefined in resultedMetaType['read']
That's very sad, since it makes this library unusable for our project, and it was almost fully integrated to it, so we'd probably will need to rewrite all the code again(((
The data, that is stored in that objects is not supposed to be queried
In the other hand - there are still ways to exceed 1MB limit - so you can't avoid that only by not allowing to use mapped object
Anyway, it worked before, if it is possible, maybe just do some config to make it possible for those, who need it, and disable it by default?
Thanks in advance
Firelord enforces some practices
one of it is banning mapped type
the biggest concern is, mapped type is very hard to query because you always need to know the value of the key in order to query
example data type:
type Data= Record<string, number>
now imagine you need to query them, how are you going to do it?
where(?, '==', 1)
well, you need to know both key
and value
, unlike data type like this
type Data= {a: number}
where('a', '==', 1)
, in this case you always know the key is going to be a
now imagine somebody created data type like this Record<string, Record<string, Record<string, number>>>
He need to know 4 information: 3 keys and 1 value before he can even query the data
maybe your intention is to reduce the cost, but I believe mapped type is a trap that could cripple your query in the future
you might want to convert them into a collection of document instead
option is a good idea, I will see what I can do
I understand why it's banned, but in our case we never use this for any data, that is meant to be queried. The data there is totally dynamic, so we cannot predict. I would even tell you, that we (almost)actually have such mapped object possible in our project as you provided as an example :). In short:
type DummyData = {
mapped: Record<string, {
_uid: string;
created_at: Timestamp;
updated_at: Timestamp;
nested: Record<string, {
status: 'active' | 'deleted',
created_at: Timestamp;
updated_at: Timestamp;
}>
}>
}
We could use array with objects, but it will be much more inconvenient to get the needed data from the object, because we will need to iterate over all array to search some entry. Updating such data will be also big headache, and I guess it's even not possible to properly check such updates in firestore rules
, but for mapped object we've managed to make reliable checks of valid data added/updated in such objects
BTW, I would also like to ask a config option, that allows to disable update behavior, that makes every update flat, since we also have some (not nested)objects, that are dynamic at all, what means Record<string, unknown>;
, and when we update it - it should be replaced fully, not merged with previous data.
For example, where there is such object: { key: 'value', key2: 2 }
, and I'm trying to update it with { key2: 3, key3: null }
- I expect it to be replaced, but instead I get { key: 'value', key2: 2, key3: null }
This feature actually is awesome, but in our case we'd rather turn it off.
For now, in our front-end we're just using original firestore's writeBatch
to create a batch, to avoid this behavior
import { writeBatch } from 'firebase/firestore';
import type { WriteBatch } from 'firelordjs';
export const createBatch = () => writeBatch() as WriteBatch;
Now I need to make some code for backend - and I'm not sure if I would be able to do such thing there
I will see what I can do tomorrow
After some considerations, I allowed Record<string, something>
type by default.
I think Firelord should bans what is impossible, not what is possible but could goes wrong, unless it requires minimal efforts from users to make things right
Firelord should not interferes too much with how users design their data model
Everything you need is available in v2.4.16
Great!! Thanks!
Will you update firelordjs as well?