Hello again. After resolving issue #89 I've got another one)
All collections in my Firestore have few required fields, that have same types, so it would be great to have some kind of AbstractMetaType, where I can put those fields, and then extend that type by the specific MetaType for the specific collection.
It will be useful again in those helper functions, described in #89, because for now they are stick to specific MetaType, so when I want to use that function to update document from another collection, i have to change $firestoreUpdate
helper's signature, which looks inconvenient.
Here is an approximate example for what do i mean:
export type FirestoreEntityData = {
_uid: string;
// STATUS
status: EntityStatus;
//
update_action: UpdateAction;
// TIMESTAMPS
created_at: ServerTimestamp;
creator_uuid: string;
created_by_platform: string;
//
updated_at: ServerTimestamp;
updated_by_uuid: string;
updated_by_platform: string;
//
deleted_at: ServerTimestamp | null;
deleted_by_uuid: string | null;
deleted_by_platform: string | null;
};
export type AbstractEntityMetaType = AbstractMetaTypeCreator<FirestoreEntityData>; // No collection name, id type and parent
// Then creating specific MetaType
export type FirestoreChatData = {
name: string;
};
export type ChatMetaType = MetaTypeCreatorFromAbstract<AbstractEntityMetaType, FirestoreChatData, 'Chats'>;
export type FirestoreUserData = {
first_name: string;
last_name: string;
};
export type UserMetaType = MetaTypeCreatorFromAbstract<AbstractEntityMetaType, FirestoreUserData, 'Users'>;
This extension may be done just by making
export type FirestoreChatData = {
name: string;
} & FirestoreEntityData;
But main idea is to make AbstractEntityMetaType
compatible with any other MetaType
, extended from it, when working with only fields, that are present in FirestoreEntityData
So then we can use it like this:
const timestamp = serverTimestamp();
type FirestoreUpdateParams<
T extends AbstractEntityMetaType,
K extends Partial<T['write']>
> = {
batch?: WriteBatch;
ref: DocumentReference<T>;
data: K;
action: string;
params?: DocumentData;
};
export function $firestoreUpdate<
T extends AbstractEntityMetaType,
K extends Partial<T['write']>,
>({
batch,
ref,
data,
action,
params = {},
}: FirestoreUpdateParams<T, K>): Promise<void> {
const mixin: K = {
update_action: {
type: action,
params,
timestamp,
},
updated_by_uuid: store.getters['auth/user'].uid,
updated_at: timestamp,
updated_by_platform: 'web' ,
};
const mixedData = {
...data,
...mixin,
};
if (batch) {
batch.update(ref, mixedData);
return Promise.resolve();
}
// No error, since all props, added in mixin are present in AbstractEntityType['Write']
return updateDoc(ref, mixedData);
}
// And usage
$firestoreUpdate({
ref: ChatRef,
data: { name: 'Test' },
});
//
$firestoreUpdate({
ref: UserRef,
data: { first_name: 'Vasya Pupkin' },
});
Maybe it's already possible, and I'm missing something.
Also I'm quite new to typescript, so maybe have some mistakes in my assumptions