JavaScript和TypeScript中的布尔值

100 阅读3分钟

boolean 是JavaScript中一个有趣的原始数据类型。在TypeScript中,它允许总共有四个值 等等,四个?

JavaScript中的布尔值#

boolean 可以取值为: 和 。其他类型的值可以是truthy或falsy,比如 或 。true false undefined null

let b = true
if(b) console.log('logged')

b = false
if(b) console.log('not logged')

b = undefined
if(b) console.log('not logged')

b = null
if(b) console.log('not logged')

除了undefinednullfalse 之外,被认为是虚假的值还有"" (空字符串)、-00 ,以及NaN

要获得任何值的布尔值,你可以使用Boolean 函数。

Boolean(false) // false
Boolean(true) // true
Boolean("false") // true ❗️
Boolean("Hey folks") // true
Boolean({}) // true
Boolean([]) // true
Boolean(123.4) // true
Boolean(Symbol()) // true
Boolean(function() {}) // true
Boolean(undefined) // false
Boolean(null) // false
Boolean(NaN) // false
Boolean(0) // false
Boolean("") // false

经验法则。所有的空值都评估为false 。空对象{} 和空数组[] (它本身就是一个对象)确实有价值,因为它们是其他值的容器。

Boolean 函数对于过滤集合中的空值非常有用。

const collection = [
  { name: 'Stefan Baumgartner', age: 37 },
  undefined,
  { name: 'D.', age: 36 },
  false
  { name: 'C.', age: 2},
  false
]

collection.filter(Boolean) // handy!

再加上Number --它将所有的值转换为它们的number 对应值或NaN ,这是一个非常酷的快速获得实际值的方法。

const x = ["1.23", 2137123, "wut", false, "lol", undefined, null]
  .map(Number)
  .filter(Boolean) // [1.23, 2137123] 👍

Boolean 它作为一个构造函数存在,具有与 函数相同的转换规则。然而,通过 ,你创建了一个包装对象,使得值的比较是真实的,但引用比较是虚假的。Boolean new Boolean(...)

const value = Boolean("Stefan") // true
const reference = new Boolean("Stefan") // [Boolean: true]

value == reference // true
value === reference // false

你可以通过.valueOf() 来获取值。

value === reference.valueOf() // true

我有一个REPL供你检查。作为一个函数,Boolean 的使用显然是很好的,但new Boolean 的用途非常有限。如果你知道一个实际的用例,请让我知道

TypeScript中的布尔类型#

boolean 在TypeScript中是一个原始类型。一定要使用小写的版本,并且不要指代对象实例,从Boolean

const boolLiteral: boolean = false // 👍
const boolObject: Boolean = false // 👎

它可以工作,但这是不好的做法,因为我们真的很少需要new Boolean 对象。

你可以在TypeScript中分配truefalseundefinednullboolean ,而不需要严格的空检查。

const boolTrue: boolean = true // 👍
const boolFalse: boolean = false // 👍
const boolUndefined: boolean = undefined // 👍
const boolNull: boolean = null // 👍

有了这个,boolean 是我们唯一可以通过联合类型完全表达的。

type MyBoolean = true | false | null | undefined // same as boolean

const mybool: MyBoolean = true
const yourbool: boolean = false

当我们启用strictNullChecks 编译器标志时,值的集合减少到truefalse

const boolTrue: boolean = true // 👍
const boolFalse: boolean = false // 👍
const boolUndefined: boolean = undefined // 💥
const boolNull: boolean = null // 💥

所以我们的集合总共减少到两个值。

type MyStrictBoolean = true | false

我们还可以通过NonNullable辅助类型来摆脱空值。

type NonNullable<T> = T extends null | undefined
  ? never
  : T;

type MyStrictBoolean = NonNullable<MyBoolean> // true | false

事实上,boolean 是由一组有限的值组成的,只在条件下使用,这使得条件类型变得很有趣。

想想看,通过一个函数在一个数据存储中进行突变。你在一个函数中设置一个标志,例如更新用户ID。那么你必须提供用户ID。

type CheckUserId<Properties, AddUserId> = 
    AddUserId extends true 
    ? Properties & { userId: string }
    : Properties & { userId?: string }

根据我们的通用AddUserId ,我们希望属性userId 被设置或者是可选。

我们可以通过从我们期望的类型中扩展我们的泛型来使这种类型更加明确

- type CheckUserId<Properties, AddUserId> = 
+ type CheckuserId<
+  Properties extends {},
+  AddUserId extends boolean
+ >
     AddUserId extends true 
     ? Properties & { userId: string }
     : Properties & { userId?: string }

在使用中,它可能会声明一个这样的函数。

declare function mutate<P, A extends boolean = false>
  (props: CheckUserId<P, A>, addUserId?: A): void

请注意,我甚至为A 设置了一个默认值,以确保CheckUserId 根据addUserId 是否被设置,给出正确的信息。

该函数在运行中。

mutate({}) // 👍
mutate({ data: 'Hello folks' }) // 👍
mutate({ name: 'Stefan' }, false) // 👍
mutate({ name: 'Stefan' }, true) // 💥 userId is missing
mutate({ name: 'Stefan', userId: 'asdf' }, true) // 👍 userId is here