首页 > 解决方案 > Typescript Pick Array 未按预期工作

问题描述

如果我将此行用作数组以及如何修复它,我不确定为什么会出现问题:

Pick<Author, PickedAuthorFields>[]

沙盒

如果我使用 never 代替条件类型,那么我在必填作者字段方面还有另一个问题。

沙盒 2

沙盒 3 可选?作者还有一个问题...

沙盒 3

许多页面需要此 ApiResBook 泛型类型,这些页面将根据请求向具有不同预期输出字段的 api 发出请求。

也许有替代方法,如果需要,我可以改变对象的形状。

// 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?

标签: typescript

解决方案


需要一段时间才能弄清楚,但我认为这是解决方案:

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 可以替换为 undefined 或任何其他单位类型


推荐阅读