打字稿和过滤器布尔

Qwe*_*tiy 2 typescript strictnullchecks

请考虑下面的代码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);
Run Code Online (Sandbox Code Playgroud)

由于以下原因,它无法编译:

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; }'.
Run Code Online (Sandbox Code Playgroud)

但绝对清楚,这false将被过滤掉.filter(Boolean)

同样的问题null

有没有办法(除了写as number[])来标记该值不包含falsenull

jus*_*est 17

您可以使用这样的功能

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[]
Run Code Online (Sandbox Code Playgroud)

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

  • IMO 这应该是公认的答案。 (3认同)

jca*_*alz 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);
Run Code Online (Sandbox Code Playgroud)

之所以有效,Boolean是因为您断言这是类型保护,并且如果回调是类型保护,那么它Array.filter()重载以返回缩小的数组。

上面的(Boolean as any as ExcludesFalse)是我能拿出的最干净的代码,它们既有效,又不会更改生成的JavaScript。将该常量Boolean声明为全局BooleanConstructor接口的一个实例,您可以将一个ExcludesFalse类似类型的类型保护签名合并到中BooleanConstructor,但不能以允许您说出来.filter(Boolean)并使其起作用的方式进行合并。您可以使用类型guard来获得更好的表现,并尝试代表防范所有虚假值(除外NaN),但您的示例不需要这样做。

无论如何,希望能有所帮助;祝好运!

  • `.filter(&lt;T&gt;(n?: T): n is T =&gt; Boolean(n))` 至少适用于 3.1.6 (4认同)
  • 你甚至可以这样做:`const ExcludesFalse = Boolean as any as &lt;T&gt;(x: T | false) =&gt; x is T;` `array.filter(ExcludesFalse);` (2认同)