Машинопись и фильтр Boolean

Рассмотрим следующий код с strictNullChecks включенный:

var a: (number | null)[] = [0, 1, 2, 3, null, 4, 5, 6];
var b: { value: number; }[] = a.map(x => x != null && { value: x }).filter(Boolean);

Не удается скомпилировать из-за:

Type '(false | { value: number; })[]' is not assignable to type '{ value: number; }[]'.
  Type 'false | { value: number; }' is not assignable to type '{ value: number; }'.
    Type 'false' is not assignable to type '{ value: number; }'.

Но совершенно ясно, что false будет отфильтровано .filter(Boolean),

Та же проблема с null,

Есть ли способ (кроме написания as number[]) отметить, что значение не содержит false или же null?

5 ответов

Решение

Если вы действительно не хотите изменять сгенерированный JavaScript, а вместо этого предпочитаете заставить компилятор TypeScript распознавать это Boolean служит защитником от false значения, вы можете сделать это:

type ExcludesFalse = <T>(x: T | false) => x is T;     
var b: { value: number; }[] = a
  .map(x => x != null && { value: x })
  .filter(Boolean as any as ExcludesFalse);

Это работает, потому что вы утверждаете, что Boolean это тип охранник, и потому Array.filter() перегружен для возврата суженного массива, если обратный вызов является защитой типа.

Выше (Boolean as any as ExcludesFalse) - самый чистый код, который я мог придумать, который работает и не меняет сгенерированный JavaScript. Постоянная Boolean объявлен экземпляром глобального BooleanConstructor интерфейс, и вы можете объединить ExcludesFalseтип подписи охранника типа в BooleanConstructor, но не таким образом, который позволяет просто сказать .filter(Boolean) и это работает. Вы можете стать более привлекательным с помощью типа guard и попытаться представить защиту от всех ложных значений ( кромеNaN) но вам не нужно это для вашего примера.

Во всяком случае, надеюсь, что это помогает; удачи!

Вы можете использовать такие функции

function nonNullable<T>(value: T): value is NonNullable<T> {
  return value !== null && value !== undefined;
}

type Truthy<T> = T extends false | '' | 0 | null | undefined ? never : T; // from lodash

function truthy<T>(value: T): value is Truthy<T> {
    return !!value;
}

[1, 2, 0, null].filter(nonNullable) // number[]
[1, 2, 0, null].filter(truthy) // number[]

NonNullable - https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

Вы можете исключить любые ненулевые значения, подобные этому

      type ValidValue<T> = Exclude<T, null | undefined | 0 | '' | false>;
const BooleanFilter = <T>(x: T): x is ValidValue<T> => Boolean(x);
var a: (number | null)[] = [0, 1, 2, 3, null, 4, 5, 6, undefined];
const values = Object.values(a).filter(BooleanFilter);
console.log(values)  // [ 1, 2, 3, 4, 5, 6 ]
      export function isTruthy<T>(value?: T | undefined | null | false): value is T {
  return !!value
}

Тогда сделайте

      const arrayWithNoFalsyValues = arrayWithFalsyValues.filter(isTruthy)

arrayWithNoFalsyValuesтип будетT[]и не будет(T | null | ...)[]

Заполните бесплатно, чтобы добавить больше ложных значений/типов к типуvalueвisTruthy(value)

Просто используйте .filter удалить любой null значения и использовать .map предоставить значение по умолчанию, если значение null что это не будет из-за filter,

var a: (number | null)[] = [0, 1, 2, 3, null, 4, 5, 6];
var b: { value: number; }[]  = a.filter(x => x != null).map(x => ({ value : x || 0 }));
Другие вопросы по тегам