【问题标题】:Typescript conversion to boolean打字稿转换为布尔值
【发布时间】:2013-11-20 10:40:00
【问题描述】:

在 Typescript 中我可以这样做:

var xxx : some_type;

if (xxx)
    foo();
else
    bar();

此处的 xxx 将被视为布尔值,无论其类型如何。

我想在函数参数中做同样的事情。我有这个功能:

function foo(b : boolean) { ... }

我希望能够调用 foo(xxx) 并将 xxx 视为布尔值,无论其类型如何。但是 Typescript 不允许这样做。

我试过了:

foo(<boolean>xxx);

但 Typescript 也不允许这样做。

我可以这样做:

foo(xxx ? true : false);

但这似乎有点傻。有没有更好的方法?

【问题讨论】:

  • 你想要做的是基于真假逻辑的松散类型。 TypeScript 的主要目的是为 JavaScript 添加静态类型,正是为了防止你进行松散的类型。因此,您实际上是在尝试做一些 TypeScript 旨在防止的事情。我建议分析你传递的参数可以是什么类型并放入重载定义中。
  • 这里的问题是一致性。如果 TypeScript 很高兴让我在 if (xxx) 中使用非布尔值,那么我没有理由不能在其他布尔上下文中使用非布尔值。在我看来,它应该要么允许两者,要么禁止两者。
  • Typescript 对此并不“满意”,Typescript 向后兼容 JavaScript。将“if”视为一个函数,其参数类型为 Any。这也是您的三元表达式有效的原​​因。 TS 不鼓励这种草率的打字,但为了向后兼容而容忍它。下面使用 !! 的答案有效,因为 not 运算符的输入是 Any,输出是布尔值。

标签: typescript


【解决方案1】:

您可以使用 Typescript 允许并且在 JavaScript 中可以正常工作的 double exclamation sign 技巧:

foo(!!xxx);

或者,将其转换为 any

foo(<any>xxx);

【讨论】:

  • 这不起作用:console.log("!!'false': ",!!'false') 给我 !!'false': true
  • 字符串 'false' 是 JavaScript (developer.mozilla.org/en-US/docs/Glossary/Truthy) 中的“真实”,因此它可以正常工作。
  • @Toolkit,在 javascript 中,通过扩展 Typescript,字符串只有在它是空字符串(或未定义)时才为假。
  • @Knaģis 是什么意思 !!xxx ?
  • @Roxy'Pro !!xxx 字面意思是“not not xxx”,所以这是一个双重否定,有效地将表达式“xxx”转换为布尔值。
【解决方案2】:

这是我对"typescript": "^3.3.3" 的解决方案:

function toBool(a: any) {
  return Boolean(a).valueOf();
}

export { toBool };

单元测试:

import { toBool } from '../../utils/bool';

describe('bool', () => {
  describe('#toBool', () => {
    it('should convert string to boolean', () => {
      expect(toBool('false')).toBeTruthy();
      expect(toBool('')).toBeFalsy();
    });
    it('should convert number to boolean', () => {
      expect(toBool(1)).toBeTruthy();
      expect(toBool(0)).toBeFalsy();
      expect(toBool(-1)).toBeTruthy();
      expect(toBool(Infinity)).toBeTruthy();
      expect(toBool(-Infinity)).toBeTruthy();
    });
    it('should convert null to boolean', () => {
      expect(toBool(null)).toBeFalsy();
    });
    it('should convert undefined to boolean', () => {
      expect(toBool(undefined)).toBeFalsy();
    });
    it('should convert NaN to boolean', () => {
      expect(toBool(NaN)).toBeFalsy();
    });
    it('should convert object to boolean', () => {
      expect(toBool({})).toBeTruthy();
    });
    it('should convert array to boolean', () => {
      expect(toBool([])).toBeTruthy();
    });
  });
});

单元测试结果:

 PASS  src/__tests__/utils/bool.spec.ts
  bool
    #toBool
      ✓ should convert string to boolean (3ms)
      ✓ should convert number to boolean (1ms)
      ✓ should convert null to boolean (1ms)
      ✓ should convert undefined to boolean
      ✓ should convert NaN to boolean (1ms)
      ✓ should convert object to boolean (1ms)
      ✓ should convert array to boolean

Test Suites: 1 passed, 1 total
Tests:       7 passed, 7 total
Snapshots:   0 total
Time:        3.79s, estimated 4s

【讨论】:

  • 错误答案:isAdd 总是正确的... (此处为 TS 2.9.1)
【解决方案3】:

虽然您不能将数字直接转换为布尔值,但您可以将其转换为包装器布尔类并立即解包。例如:

foo(<boolean><Boolean>xxx);

虽然笨拙,但它避免了类型擦除转换为&lt;any&gt;。与!! 方法相比,它也可以说不那么晦涩且更具可读性(在转译的 js 代码中肯定如此)。

【讨论】:

  • 有用的答案,谢谢。但我想补充一点,我已经在 javascript 和 typescript 的许多地方看到(并使用过)!! 方法,所以我认为“晦涩难懂”的论点不是很可靠。我个人认为它比双重转换更具可读性。
  • 双重转换似乎写起来很长,读起来很垃圾,而!!对于真正的初级javascript开发人员来说只是晦涩难懂。
【解决方案4】:

使用 TypeScript 2.0.2,您可以这样做:

type Falsey = '' | 0 | false | null | undefined;

function eatFruit(fruit: string | Falsey) { 
  if (fruit) {
    alert(`Ate ${fruit}`);
  } else {
    alert('No fruit to eat!');
  }
}

const fruits = ['apple', 'banana', 'pear'];
eatFruit(fruits[0]); // alerts 'Ate apple'
eatFruit(fruits[1]); // alerts 'Ate banana'
eatFruit(fruits[2]); // alerts 'Ate pear'
eatFruit(fruits[3]); // alerts 'No fruit to eat!'

const bestBeforeDay = 12;
let day = 11;
eatFruit(day < bestBeforeDay && 'peach'); // alerts 'Ate peach'
day += 1;
eatFruit(day < bestBeforeDay && 'peach'); // alerts 'No fruit to eat!'

let numMangos = 1;
eatFruit(numMangos && 'mango'); // alerts 'Ate Mango'
numMangos -= 1;
eatFruit(numMangos && 'mango'); // alerts 'No fruit to eat!'

【讨论】:

    【解决方案5】:

    使用这个

    YourMethod(!!isEnabled);
    

    '!!'用于类型转换为布尔值

    【讨论】:

    • 考虑在代码中添加一些解释。
    【解决方案6】:
    foo(!!xxx); // This is the common way of coercing variable to booleans.
    // Or less pretty
    foo(xxx && true); // Same as foo(xxx || false)
    

    但是,每次在代码中调用 foo 时,您可能最终都会复制双键,因此更好的解决方案是将强制转换为函数 DRY 内的布尔值

    foo(xxx);
    
    foo(b: any){
      const _b = !!b;
      // Do foo with _b ...
    }
      /*** OR ***/
    foo(b: any){
      if(b){
        // Do foo ...
      }
    }
    

    【讨论】:

    • 如上所述:非空字符串不会神奇地转换为等效的布尔值 if ("false") { console.info("I'm not false"); } // 这将记录
    【解决方案7】:

    这是一个简单的函数,可以处理大多数情况,包括将布尔值作为输入处理(以防万一):

    type Falsey = undefined | null;
    const parseBoolean = (val: string | boolean | number | Falsey): boolean => {
      const s = val && val.toString().toLowerCase().trim();
      if (s == 'true' || s == '1')
        return true;
      return false; 
    }
    

    还有一个有趣的测试:

    describe('Boolean Parser', () => {
        [
            { val: 'true', expected: true },
            { val: 'false', expected: false },
            { val: 'True', expected: true },
            { val: 'False', expected: false },
            { val: 'TRUE', expected: true },
            { val: 'FALSE', expected: false },
            { val: '', expected: false },
            { val: '1', expected: true },
            { val: '0', expected: false },
            { val: false, expected: false },
            { val: true, expected: true },
            { val: undefined, expected: false },
            { val: null, expected: false },
            { val: 0, expected: false },
            { val: 1, expected: true },
            { val: 111, expected: false }
        ].forEach(args => {
            it(`should parse ${args.val} to boolean`, () => {
                expect(parseBoolean(args.val)).toBe(args.expected);
            });
        })
    });
    

    【讨论】:

      【解决方案8】:

      使用 typescript 最明显的方法是使用布尔构造函数:

      Boolean(someVal);
      

      你的情况是:

      foo(Boolean(xxx));
      

      请注意,使用的构造函数没有“new”关键字。因为如果添加它,您将创建一个新的布尔对象而不是强制转换值:

      Boolean(false) == false 
      

      但是

      new Boolean(false) == true
      

      因为它是一个对象

      【讨论】:

      • 谢谢@fs_dm,这实际上比!!xxx清晰得多。
      【解决方案9】:

      if(xxx) {...} //如果 xxx 不是未定义或为空,则读取为 TRUE if(!xxx) {...} //如果 xxx 未定义或为空,则读取为 TRUE

      对于像 'true' 或 'false' 这样的字符串: xxx.toLowerCase().trim() === 'true' ?真:假

      所以:

      var zzz = 'true'; //string
      var yyy = [];  //array
      

      ...

      if(zzz.toLowerCase().trim() === 'true') { ... }  // quick string conversion
      

      ...

      if(yyy ? true : false) { ... }  // quick any conversion - it's TRUE if it's not null or undefined
      

      ...

      // in a catch-all function
      
      if(toBoolean(zzz)) { ... }
      if(toBoolean(yyy)) { ... }
      
      
      toBoolean(xxx: any): boolean {
        if(xxx) {
          const xStr = xxx.toString().toLowerCase().trim();
          if(xStr === 'true' || x === 'false') {
            return xStr === 'true' ? true : false;
          } else {
            return xxx ? true : false;
          }
        } else {
          return false;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-27
        • 2019-04-21
        • 2018-01-24
        • 2019-05-03
        • 2018-09-07
        • 2019-07-24
        • 2016-06-16
        相关资源
        最近更新 更多