Seems Typescript is not smart enough to understand the type when looping it, so I need to simplify it when I want to process the array, and let the complex type only for type cohertion:
type Item<Id extends string> = {
id: Id,
isFixed?: boolean
}
type FixedItem<Id extends string> = Item<Id> & {
isFixed: true
}
type NotFixedItem<Id extends string> = Item<Id> & {
isFixed?: false
}
type Items<Id extends string> = NotFixedItem<Id>[] | [FixedItem<Id>, ...NotFixedItem<Id>[]]
const items: Items<'dog' | 'cat' | 'horse'> = [
{id: 'dog', isFixed: true},
{id: 'horse', isFixed: false},
{id: 'cat'},
]
// items here is a much more general type
const loopItems = <Id extends string>(items: Item<Id>[]) => items.map((item) => {
// item is understood as Item<Id>
}
// the complex type Items<Id> is an specific case of Item<Id>[] so the param is valid
loopItems(items)