I have a function that send an object that got { name: { value: string }, some unknown property }
, how can I type my parameter to accept this object if he got at least { name: { value: string } } ?
Example:
// Working but is there a specific type to explicitly do this without [x:string]: any ?
const sortNameV2 = (array: Array<{ name: { value: string }, [x:string]: any }>, sortOrder: 'ASC' | 'DESC') => {
return [...array]
.sort((a, b) =>
a.name.value.localeCompare(b.name.value)
)
}
sortNameV2([{ name: { value: 'titi'}, id: 1 }], 'ASC')
CodePudding user response:
Make it a generic type argument using extends
:
// Working but is there a specific type to explicitly do this without [x:string]: any ?
const sortNameV2 = <ElementType extends { name: { value: string } }>(array: Array<ElementType>, sortOrder: 'ASC' | 'DESC') => {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−^^^^^^^^^^^^^
return [...array]
.sort((a, b) =>
a.name.value.localeCompare(b.name.value)
)
}
sortNameV2([{ name: { value: 'titi'}, id: 1 }], 'ASC')
CodePudding user response:
Not answering your question directly.
Working with generics might get confusing. My suggestion is that you do not create a function that sorts the array but rather just the comparer. Maybe it would be more reusable, because it allows the user to decide whether to create a copy or to sort in place. Also you could wrap it in a curried function that gets passed a sort order.
type ItemWithName = { name: { value: string }}
const sortNameComparer(order: 'ASC' | 'DESC' = 'ASC') {
return (a: ItemWithName, b: ItemWithName) =>
a.name.value.localeCompare(b.name.value) * (
order === 'ASC' ? 1 : -1
)
}
// usage
[{ name: { value: 'titi'}, id: 1 }].sort(sortNameComparer('ASC'))