I am trying to create a union type from the elements of an array in an object that has been annotated to a mapped type. Is it possible to achieve somehow without removing the type annotation?
Example code:
type Persons<Name extends string> = {
readonly [N in Name]: {
readonly age: number;
readonly friends: ReadonlyArray<Name>;
};
}
type Friends<Name extends string, P extends Persons<Name>, N extends Name> = P[N]["friends"][number]
type Names = 'Bill' | 'Jim' | 'Tom'
// Example with type annotation that I would like to keep
const persons1: Persons<Names> = {
Bill: {
age: 40,
friends: ['Jim']
},
Jim: {
age: 42,
friends: ['Tom']
},
Tom: {
age: 45,
friends: []
}
}
// Example without type annotation (for which it works as expected)
const persons2 = {
Bill: {
age: 40,
friends: ['Jim']
},
Jim: {
age: 42,
friends: ['Tom']
},
Tom: {
age: 45,
friends: []
}
} as const
type Friends1 = Friends<Names, typeof persons1, 'Jim'>
// 'Jim' | 'Bill' | 'Tom' - would like it to be 'Tom'
type Friends2 = Friends<Names, typeof persons2, 'Jim'>
// 'Tom' - as wanted
My guess was that it could be done by deep cloning persons1 but haven't been able to get the correct type of the clone.