I'm not sure why there is a problem if i use this line as array and how to fix it:
Pick<Author, PickedAuthorFields>[]
Sandbox.
If i use never instead of conditional type, than i have another problem with required author field.
Sanbox 2
Sandbox 3 with optional ? author had another problems...
Sanbox 3
This ApiResBook generic type is needed for many pages that will make requests to api with different expected output fields based on request.
Maybe there is alternative approach, i can change shape of object if needed.
// Main types as in database - should't be changed
type Book = {
id: string
title: string
visible: boolean
author: string
}
type Author = {
id: string
name: string
}
// Inhereted from types from main
type BookFields = keyof Book
type AuthorFields = keyof Author
// type for generating expected fetch response from API
type ApiResBook<
PickedBookFields extends BookFields,
PickedAuthorFields extends AuthorFields | undefined = undefined,
> = {
book: Pick<Book, PickedBookFields> & {
author: PickedAuthorFields extends AuthorFields ? Pick<Author, PickedAuthorFields>[] : undefined
}
}
// tests
type BookWithAuthor = ApiResBook<'id', 'name' | 'id'>
// should be ok
const bookWithAuthor1: BookWithAuthor = { book: { id: '1', author: [{ id: '1' }] } }
const bookWithAuthor2: BookWithAuthor = { book: { id: '1', author: [{ name: 'Max' }] } }
const bookWithAuthor3: BookWithAuthor = { book: { id: '1', author: [{ name: 'Max', id: '1' }] } } // why error?
It was a while to figurate out but I think this is the solution:
type Book = {
id: string
title: string
visible: boolean
author: string
}
type Author = {
id: string
name: string
}
// Inhereted from types from main
type BookFields = keyof Book
type AuthorFields = keyof Author
// type for generating expected fetch response from API
type ApiResBook<
PickedBookFields extends BookFields,
PickedAuthorFields extends AuthorFields | null = null,
AuthorObj = {author: Pick<Author, Exclude<PickedAuthorFields, null>>[]}
> = {
book: Pick<Book, PickedBookFields> & (PickedAuthorFields extends null ? {} : AuthorObj)
}
// tests
type BookWithAuthor = ApiResBook<'id', 'name' | 'id'>
type BookWithoutAuthor = ApiResBook<'id'>
// should be ok
const bookWithAuthor0: BookWithoutAuthor = { book: { id: '1' } }
const bookWithAuthor3: BookWithAuthor = { book: { id: '1', author: [{ id: '1', name: 'Max' }] } }
PS. null can be replaced by undefined or any other unit type
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With