It appears challenging to directly access the string values within userIds
without utilizing a generic type parameter:
type UserList<T extends ReadonlyArray<string>> = {
userIds: T
userData: {
[UserId in T[number]]: {
userId: UserId
username: string
}
}
}
Your type definition would need to be structured like this:
const a: UserList<['hello']> = {
userIds: ['hello'],
userData: {
hello: {
userId: 'hello',
username: 'username'
}
}
}
To avoid specifying user IDs twice, you may need to utilize a wrapper function as described here:
function asUserList<T extends ReadonlyArray<string>>(list: UserList<T>) {
return list;
}
const a = asUserList({
userIds: ['hello'] as const,
userData: {
hello: {
userId: 'hello',
username: 'username'
}
}
})
If you opt not to use a generic parameter and attempt to leverage the this
type within an interface like so:
interface UserList {
userIds: string[]
userData: {
[UserId in this['userIds'][number]]: {
userId: UserId
username: string
}
}
}
This approach is not effective because this['userIds']
will consistently result in the weaker string[]
type, rather than enabling robust typing of userData
based on the specific values in userIds
.