如何在 Typescript 中类型检查二进制类型别名

How to type check a binary type alias in Typescript

我想根据参数的给定类型来确定条件,但由于所有可能的参数都是相同的二进制类型(数字),我正在寻找一种方法来创建某种类型别名,它可以被检查。

这是最初的想法,行不通,因为 typescript 被编译成 javascript,因此 bonus 将永远是 javascript 类型 number

    type Percentage = number;

    class Foo {
      applyBonus(bonus: Percentage | number) {
        if (typeof bonus === 'Percentage') {
          console.log('Percent');
        } else {
          // it's always number, because at execution time we're in javascript land here
          console.log('number'); 
        } 
      }
    }

    let bar = new Foo();
    bar.applyBonus(5);
    bar.applyBonus(6 as Percentage);

这个问题主要是针对typescript语言的可能性,以及是否可以通过typescript特性来解决。很容易使用 {value:6,type:'percent'} 这样的对象来代替二进制类型的数字。

Typescript 不是根据事物的名称来打字,而是根据事物的结构来打字。你可以给一个数字起别的名字,但它仍然是一个数字。 Percentage这里只是别名

执行此类操作的更好方法是创建一个具有独特形状的界面,您可以在运行时轻松识别它。

interface Percentage { percentage: number }

class Foo {
   applyBonus(bonus: Percentage | number) {
      if (typeof bonus === 'object') {
         console.log('Percent', bonus.percentage);
      } else {
         console.log('number', bonus); 
      } 
   }
}

new Foo().applyBonus(123)
new Foo().applyBonus({ percentage: 456 })

Playground


或者(我不推荐这个,但在学术上很有趣),你可以继承 Number 并使用它。

class Percentage extends Number { }

class Foo {
   applyBonus(bonus: Percentage | number) {
      if (bonus instanceof Percentage) {
         console.log('Percent', bonus);
      } else {
         console.log('number', bonus); 
      } 
   }
}

new Foo().applyBonus(123)
new Foo().applyBonus(new Percentage(456))

但实际上,我会质疑您对此的需求。我不确定您要在这里完成什么,但可能有更简单的方法。

代码示例

type Percentage = number;

    class Foo {
      applyBonus(bonus: Percentage | number) {
        if (typeof bonus === 'Percentage') {
          console.log('Percent');
        } else {
          // NO, IT IS NOT ALWAYS NUMBER BECAUSE OF THAT
          console.log('number'); 
        } 
      }
    }

    let bar = new Foo();
    bar.applyBonus(5);
    bar.applyBonus(6 as Percentage);

真实原因

JavaScript

JavaScript 以及其他任何编程语言,都带有一组原始值。因为 es6Six

  • 人数
  • 字符串
  • 布尔值
  • 未定义
  • 符号

如您所见,Percentage 不是其中之一。

您的 execution time we're in javascript land here 语句中可能正确的是类型 "do not exists on JS" 的事实 ... 不完全正确,因为类型确实存在于 JS 中,但您的示例中的编译代码看起来有些像这样

class Foo {
    applyBonus(bonus) {
      if (typeof bonus === 'Percentage') {
        console.log('Percent');
      } else {
        console.log('number'); 
      } 
    }
  }

  let bar = new Foo();
  bar.applyBonus(5);
  bar.applyBonus(6);

如果我们看一下 bar.applyBonus 你传递的是 5 n 6 这是两个原始值他们是数字

如果你不相信我打开浏览器的控制台并粘贴这个 typeof 5

和"Percentage" !== "number"

这就是为什么你总是进入 else 的原因。获得 instanceof 百分比的唯一方法是创建对象调用 Percentage:

class Percentage {
  constructor (value) {
     this.value = value;
  }
}

 class Foo {
      applyBonus(bonus) {
        if (bonus instanceof === Percentage) {
          console.log('Percent');
        } else {
          // NO, IT IS NOT ALWAYS NUMBER BECAUSE OF THAT
          console.log('number'); 
        } 
      }
    }

    let bar = new Foo();
    bar.applyBonus(5);
    bar.applyBonus(new Percentage(6));