Reputation: 36876
Is there a way to force all elements in array?
Only requirement is "type connection" to main Book type.
I hope there is some way to make tuple type ['id', 'title'] from Book type generically, as suggested in comments. Or at least array length check...
type Book = {
id: string
title: string
visible: boolean
author: string
}
type BookFields = keyof Book
type BookFieldsExtract<ExtractedFields extends BookFields> = Extract<BookFields, ExtractedFields>
const arr: BookFieldsExtract<'id' | 'title'>[] = ['id'] // how to force error if title not inclided in array?
Use case:
type SelectedBookFields = BookFieldsExtract<'id' | 'title'>
type ApiRes = ApiResBook<SelectedBookFields> // {book: {id: string, title: string}}
const bookFields: SelectedBookFields[] = ['id', 'title'] // i just don't want to forget some fields when making request
const response = await fetchAPI<ApiReqBookBody, ApiRes>(
'book',
{ fields: { book: bookFields } }
) // response type is {error: true} | {book: {id: string, title: string}}
Upvotes: 1
Views: 1571
Reputation: 36876
After some search, found a way that works for my use case:
const bookFields: ['id', 'title'] = ['id', 'title']
type BookFields = typeof bookFields[number] // 'id' | 'title'
Upvotes: 0
Reputation: 20162
I dont know if it will work for you, but I would create some value constructor for this tuple with some overloads in order to guide the dev. Consider:
function makeArrFromKeys<T, A extends keyof T>(obj: T, key1: A): [A]
function makeArrFromKeys<T, A extends keyof T, B extends keyof Omit<T, A>>(obj: T, key1: A, key2: B): [A, B]
function makeArrFromKeys<T, A extends keyof T, B extends keyof Omit<T, A>, C extends keyof Omit<T, A | B>>(obj: T, key1: A, key2: B, key3: C): [A,B,C]
function makeArrFromKeys<T, K extends keyof T>(obj: T, ...keys: K[]): K[] {
return keys;
}
const book: Book = {
id: 'i',
title: 't',
visible: true,
author: 'a'
}
const arr = makeArrFromKeys(book, 'id', 'author', 'title')
// arr has type ['id', 'author', 'title']
Our function is extends to three keys, but if you will follow overloads you can go further. Function will make the tuple exactly how you wanted - keys are unique and if you provide you need 'id', 'title' you will get ['id', 'title']
.
I would name it compromise between a crazy type which probably we can do, and just maintainable and safety code.
Upvotes: 1