TypeScript - проверка элементов на карте массива - PullRequest
0 голосов
/ 09 февраля 2020

У меня есть интерфейс для книги с необязательным идентификатором (для новой книги, которая еще не сохранена на сервере):

interface Book {
   id?: string
}

Когда я получаю все книги из бэкэнда - я использую для создать объект byId:

allIds: payload.map(book => book.id!),

, где allIds объявление:

allIds: string[]

, как вы можете видеть, я добавил ! после book.id, чтобы указать У каждой книги есть идентификатор. как будто я не буду этого делать, Typescript не будет компилироваться с:

TS2322: Тип '(string | undefined) []' нельзя назначить типу 'string []'.

Тип 'строка | undefined 'нельзя назначить типу' string '.

Тип' undefined 'нельзя назначить типу' string '.

Теперь, он работает с !, и Я не ожидаю, что в какой-либо книге пропущен ее идентификатор, но я хотел бы найти элегантный способ проверить его ... на всякий случай.

Я могу сделать что-то вроде:

allIds: payload.map(book => {
   if (!book.id) {
      throw new Error("invalid book id")
   }
   return book.id
}),

но я хотел бы знать, есть ли у вас идея более элегантного однострочного элегантного решения для проверки элементов при его сопоставлении.

Ответы [ 2 ]

1 голос
/ 09 февраля 2020

Я не ожидаю, что в какой-либо книге пропущен ее идентификатор

Затем удалите ? из интерфейса.

Если вы хотите отфильтровать элементы без id, то allIds будут все строки, и если вы настаиваете на одной строке:

const allStrings: string[] = payload.map(book => book.id).filter(<T>(v: T): v is Exclude<T, undefined> => typeof v !== 'undefined');

Если по какой-то причине вы не У вас нет доступа к интерфейсу Book, вы можете использовать этот тип для входящих данных:

Required<Book>

, что сделает id больше не обязательным.

1 голос
/ 09 февраля 2020

Как насчет инкапсуляции логов подтверждения c в отдельную функцию?

function assertDefined<T>(t: T | undefined | null): T {
    if (t == undefined) throw new Error("undefined or null item.")
    return t
}

const res = payload.map(book => assertDefined(book.id)) // string[]

Вы можете определить функцию propOrThrow, чтобы сделать ее немного короче:

function propOrThrow<T, U>(mapper: (t: T) => U | undefined) {
    return (t: T): U => assertDefined(mapper(t))
}

const res2 = payload.map(propOrThrow(b => b.id)) // string[]

Пример кода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...