Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
252 views
in Technique[技术] by (71.8m points)

TypeScript filter out nulls from an array

TypeScript, --strictNullChecks mode.

Suppose I have an array of nullable strings (string | null)[]. What would be a single-expression way to remove all nulls in a such a way that the result has type string[]?

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

Array.filter does not work here:

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

Array comprehensions could've work but they are not supported by TypeScript.

Actually the question can be generalized to the problem of filtering an array of any union type by removing entries having one particular type from the union. But let's focus on unions with null and perhaps undefined as these are the most common usecases.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can use a type predicate function in the .filter to avoid opting out of strict type checking:

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);

Alternatively you can use array.reduce<string[]>(...).

2021 update: stricter predicates

While this solution works in most scenarios, you can get a more rigorous type check in the predicate. As presented, the function notEmpty does not actually guarantee that it identifies correctly whether the value is null or undefined at compile time. For example, try shortening its return statement down to return value !== null;, and you'll see no compiler error, even though the function will incorrectly return true on undefined.

One way to mitigate this is to constrain the type first using control flow blocks, and then to use a dummy variable to give the compiler something to check. In the example below, the compiler is able to infer that the value parameter cannot be a null or undefined by the time it gets to the assignment. However, if you remove || value === undefined from the if condition, you will see a compiler error, informing you of the bug in the example above.

function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
  if (value === null || value === undefined) return false;
  const testDummy: TValue = value;
  return true;
}

A word of caution: there exist situations where this method can still fail you. Be sure to be mindful of issues associated with contravariance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

62 comments

56.7k users

...