[typescript] TypeScript는 배열에서 null을 필터링합니다.

TypeScript, –strictNullChecks 모드.

nullable 문자열 배열 (string | null) []이 있다고 가정합니다. 결과가 string [] 유형을 갖는 방식으로 모든 널을 제거 하는 단일 표현식 방법 은 무엇입니까 ?

const array: (string | null)[] = ["foo", "bar", null, "zoo", null];
const filterdArray: string[] = ???;

Array.filter는 여기서 작동하지 않습니다.

// Type '(string | null)[]' is not assignable to type 'string[]'
array.filter(x => x != null);

배열 이해는 작동 할 수 있지만 TypeScript에서 지원되지 않습니다.

실제로 질문은 공용체에서 특정 유형을 가진 항목을 제거하여 모든 공용체 유형의 배열을 필터링하는 문제로 일반화 될 수 있습니다. 그러나 가장 일반적인 사용 사례이므로 null 및 undefined 인 공용체에 중점을 둡니다.



답변

엄격한 유형 검사에서 옵트 아웃하지 않도록 에서 유형 술어 함수를 사용할 수 있습니다 .filter.

function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
    return value !== null && value !== undefined;
}

const array: (string | null)[] = ['foo', 'bar', null, 'zoo', null];
const filteredArray: string[] = array.filter(notEmpty);

또는 array.reduce<string[]>(...).


답변

@ bijou-trouvaille의 답변과 유사하게 <arg> is <Type>필터 함수의 출력으로 를 선언하면 됩니다.

array.filter((x): x is MyType => x !== null);


답변

더 많은 사람들이 종종 잊어으로 좋은 측정을위한 하나의 flatMap처리 수 filtermap(이것은 또한 어떤 캐스팅을 필요로하지 않는 한 번에 string[]) :

// (string | null)[]
const arr = ["a", null, "b", "c"];
// string[]
const stringsOnly = arr.flatMap(f => typeof f === "string" ? [f] : []);


답변

filter결과를 원하는 유형으로 캐스팅 할 수 있습니다 .

const array: (string | null)[] = ["foo", "bar", null, "zoo", null];
const filterdArray = array.filter(x => x != null) as string[];

이것은 언급 한보다 일반적인 사용 사례에서 작동합니다. 예를 들면 다음과 같습니다.

const array2: (string | number)[] = ["str1", 1, "str2", 2];
const onlyStrings = array2.filter(x => typeof x === "string") as string[];
const onlyNumbers = array2.filter(x => typeof x === "number") as number[];

( 놀이터의 코드 )


답변

유형 검사가 필터링 된 유형을 반환 유형과 다르지 않게 만드는 것을 제외하고는 모든 것이 좋다고 생각합니다.

const array: (string | null)[] = ["foo", "bar", null, "zoo", null];
const filterdArray: string[] = array.filter(f => f !== undefined && f !== null) as any;
console.log(filterdArray);


답변

또 다시 나는 함수가 호출 번들을 통해 동일한 유형의 가드 도우미 함수를 작성하는 데 모든 사람을 피하기 위해 isPresent, isDefined그리고 isFilled헬퍼 라이브러리로 : https://www.npmjs.com/package/ts-is-present

현재 유형 정의는 다음과 같습니다.

export declare function isPresent<T>(t: T | undefined | null): t is T;
export declare function isDefined<T>(t: T | undefined): t is T;
export declare function isFilled<T>(t: T | null): t is T;

다음과 같이 사용할 수 있습니다.

import { isDefined } from 'ts-is-present';

type TestData = {
  data: string;
};

const results: Array<TestData | undefined> = [
  { data: 'hello' },
  undefined,
  { data: 'world' }
];

const definedResults: Array<TestData> = results.filter(isDefined);

console.log(definedResults);

Typescript가이 기능을 번들로 제공 할 때 패키지를 제거하겠습니다. 그러나 지금은 즐기십시오.


답변

이미 Lodash를 사용하고 있다면 compact. 또는 Ramda를 선호하는 경우 ramda-adjunct도 compact작동합니다.

둘 다 유형이 있으므로 tsc가 만족하고 결과적으로 올바른 유형을 얻습니다.

Lodash d.ts 파일에서 :

/**
 * Creates an array with all falsey values removed. The values false, null, 0, "", undefined, and NaN are
 * falsey.
 *
 * @param array The array to compact.
 * @return Returns the new array of filtered values.
 */
compact<T>(array: List<T | null | undefined | false | "" | 0> | null | undefined): T[];