Машинопись и фильтр 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 }));