In my current project, I am implementing a unique custom type called "RecordsByType", which is currently undefined in the code snippet below.
Within this snippet, I have various types that represent database records, each with its type defined within a nested attribute named ["attributes"]["type"]. For instance, take a look at the Account type. Unfortunately, this specific aspect cannot be altered or modified.
It's worth noting that there will be numerous different "RecordTypes" beyond just Account or User.
type RecordTypeName = 'Account' | 'User';
type RecordType = Account | User;
type RecordKey = keyof DbRecord | keyof Account | keyof User;
interface DbRecord {
attributes: {
type: RecordTypeName;
};
}
interface Account extends DbRecord {
attributes: {
type: 'Account';
};
name: string;
}
interface User extends DbRecord {
attributes: {
type: 'User';
};
email: string;
}
const account1: Account = { attributes: { type: 'Account' }, name: 'A1' };
const account2: Account = { attributes: { type: 'Account' }, name: 'A2' };
const user: User = { attributes: { type: 'User' }, email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="91f4fcf0f8fdd1f4fcf0f8fdbff2fefc">[email protected]</a>' };
type RecordsByType = unknown;
// The following line contains initial values to demonstrate the expected type structure,
// but it should also be able to initialize without any values as '= {};' would suffice.
const recordsByType: RecordsByType = {
Account: [account1, account2],
User: [user]
};
// This line should compile successfully, resulting in an array of Accounts rather than generic DbRecords[] or RecordType[].
const accounts: Account[] = recordsByType['Account'] || [];
// The next line should trigger a compilation error since the user object is not an instance of Account.
recordsByType['Account']?.push(user);
This related question may offer some insights, although my situation involves a nested key "attribute" and is not as generic.
First Attempt:
Initially, I attempted to define the RecordsByType type using Partial
type RecordsByType = Partial<Record<DbRecord['attributes']['type'], DbRecord[]>>;
// => Type DbRecord[] is not assignable to type Account[]
Second Attempt:
I then tried matching the "type" value with the record's actual value, only to face similar complications.
type RecordsByType<
T extends K['attributes']['type'],
K extends RecordType
> = Partial<Record<T, K[]>>;
// The following line results in RecordType[], not Account[], causing a compilation error
const accounts: Account[] = recordsByType['Account'] || [];
Final Thoughts:
My goal is to establish a connection between each record's ["attributes"]["type"] and the corresponding "key" value while being able to retrieve a list of specific implementations for each key instead of a generic type.