Как сказать Typescript, что loda sh .filter () делает что-то ненулевое? - PullRequest
0 голосов
/ 21 февраля 2020

Я недавно начал использовать Typescript, и я использую строгий режим. Во многих случаях у меня есть список значений Nullable, и я использую _.filter () для удаления нулей. Например,

const users: {id: number, name: string | null}[] = getUsers()
const lowerCaseNames = _(users)
  .filter(user => !!user.name)
  .map(user => user.name.toLowerCase())
  .value()

Это не работает, потому что Typescript все еще думает, что user.name может быть нулевым, поэтому user.name.toLowerCase () недопустимо. Вместо этого мне пришлось разделить цепочку по нескольким переменным и использовать Typecast, оба из которых неудачны:

const users: {id: number, name: string | null}[] = getUsers()
const usersWithNames: {id: number, name: string}[] = _.filter(user => !!user.name) as {id: number, name: string}[]
const lowerCaseNames = _.map(usersWithNames, user => user.name.toLowerCase())

Есть ли способ сообщить lodash / typcript, что .filter() избавляется от нули без типа или без разрыва цепочки?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 21 февраля 2020

Вы можете использовать защиту типа внутри filter

type User = { id: number; name: string | null }

const haveName = (user: User): user is User & { name: string } => user.name !== null

const users: User[] = []

const lowerCaseNames = _(users)
  .filter(haveName)
  .map(user => user.name.toLocaleLowerCase())
  .value()
2 голосов
/ 21 февраля 2020

@ Ответ Асафа Авива находится на правильном пути с охранниками типов.

Вот обобщенная c версия, которая работает, даже если вы не хотите указывать тип для User:

declare const users: {id: number, name: string | null}[];
const notNull = <K extends string>(key: K) =>
    <T extends { [k in K]: T[K] }>(val: T): val is T & { [k in K]: Exclude<T[K], null> } =>
        val[key] !== null;

const lowerCaseNames = _(users)
  .filter(notNull('name'))
  .map(user => user.name.toLowerCase())
  .value();
...