149

我正在试验TypeScript,并且在创建一个ID应该是一个字段的类的过程中integer,我有点困惑。

首先,在带有 TypeScript 插件的 Visual Studio 2012 中,我int在智能感知类型列表中看到。但我得到一个编译错误,上面写着:

当前范围内不存在名称“int”。

我查看了语言规范,只看到以下原始类型:numberstringbooleannullundefined。没有integer类型。

所以,我有两个问题:

  1. 我应该如何向我班级的用户表明一个特定的字段不仅仅是一个number,而是一个integer(而不是一个floating点或decimal数字)?

  2. int如果它不是有效类型,为什么我会在智能感知列表中看到它?

更新:到目前为止,我得到的所有答案都是关于如何JavaScript没有 int 类型,在运行时很难强制执行int类型......我知道这一切。我在问是否有TypeScript办法向我班级的用户提供注释,该字段应该是integer. 也许是某种特定格式的评论?

4

9 回答 9

143
  1. 我认为没有直接的方法来指定数字是整数还是浮点数。在 TypeScript 规范第 3.2.1 节中,我们可以看到:

    “...Number 原始类型对应于类似名称的 JavaScript 原始类型,表示双精度 64 位格式 IEEE 754 浮点值...”

  2. 我认为int是 Visual Studio 智能感知中的一个错误。正确的是number

于 2012-10-15T15:05:28.843 回答
40

TypeScript 是 JavaScript 的超集,它没有 int 的概念。它只有一个数字的概念,它有一个浮点数。

一般来说,编译器必须做的工作量来强制 TypeScript int 类型的整数可能是巨大的,在某些情况下,仍然无法确保在编译时只分配整数,这就是为什么无法可靠地将一个添加int到 TypeScript 的原因。

当您最初在 Visual Studio 中获得 intelliSense 时,工具无法确定要提供什么,因此您可以获得包括 int 在内的所有内容 - 但一旦您处理已知类型的内容,您将获得明智的 intelliSense。

例子

var myInt: number;
var myString: string;

myInt. // toExponential, toFixed, toPrecision, toString
myString. // charAt, charCodeAt, concat, indexOf, lastIndexOf, length and many more...
于 2012-10-15T15:06:00.177 回答
24

在 TypeScript 中,您可以使用标记来近似有时称为不透明类型的内容。

// Helper for generating Opaque types.
type Opaque<T, K> = T & { __opaque__: K };

// 2 opaque types created with the helper
type Int = Opaque<number, 'Int'>;
type ID = Opaque<number, 'ID'>;

// using our types to differentiate our properties even at runtime
// they are still just numbers
class Foo {
    someId: ID;
    someInt: Int;
}

let foo = new Foo();

// compiler won't let you do this due to or markers
foo.someId = 2;
foo.someInt = 1;

// when assigning, you have to cast to the specific type
// NOTE: This is not completely type safe as you can trick the compiler 
// with something like foo.someId = 1.45 as ID and it won't complain.
foo.someId = 2 as ID;
foo.someInt = 1 as Int;

// you can still consume as numbers
let sum: number = foo.someId + foo.someInt;

这样做可以让您在代码中更明确地说明属性期望的类型,并且编译器不允许您在没有强制转换的情况下分配原始值。这不会产生任何额外的 .js 输出,您仍然可以使用这些值作为它们所基于的任何类型。在此示例中,我使用的是数字,但您也可以在字符串和其他类型上使用。

在这个例子中,你仍然可以欺骗编译器接受不是 Int 或 Id 的东西,但如果你试图将 1.45 分配为 Int 或类似的东西,它应该会跳出来。您还可以选择创建用于创建值以提供运行时验证的辅助函数。

有许多不同的方法可以创建“标记”类型。这是一篇好文章:https ://michalzalecki.com/nominal-typing-in-typescript/

于 2018-05-25T03:49:21.957 回答
19

TypeScript 中没有integerfloat只有number类型,就像在 JavaScript 中一样。但是如果你想告诉程序员你期望integer类型,你可以尝试使用类型别名,比如

type integer = number;
type float = number;

// example:
function setInt(id: integer) {}

但这仍然是number类型,您可以获得float.

文档中的部分描述:
“别名实际上并没有创建新类型 - 它创建了一个新名称来引用该类型。为原语起别名并不是非常有用,尽管它可以用作文档的一种形式。”

于 2018-09-08T11:06:40.537 回答
19

这对我来说是谷歌上的最高结果,所以我认为我应该提供我找到的解决方案。

使用bigint

现在是 2020 年并且bigint已被接受,值得一提。您可以简单地执行以下操作。请注意,bigint与 a 相比, s 对性能的影响更大number

const myNumber: bigint = 10n


使用标称类型/标记类型/不透明类型

另一种方法是使用标称类型,但可以说它不太符合人体工程学,我不确定它是否比 快bigint,但该模式确实可以推广到任何类型,而不仅仅是number. TypeScript 对此没有“一流”的支持,所以你必须做一个厚颜无耻的 hack。有一个用于此调用的库newtype-ts,其中包括常见类型,Integer因此您可能只想使用它,但我将在下面解释其工作原理。

首先,我们定义integer类型。

const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }

确保我们有一个唯一的TAG值,这样我们就不会意外地使用相同的键创建一个对象,并且出于同样的原因,我们也使该字段成为唯一的符号。现在,您的整数实际上不会有这个对象字段,但这很好。

有了这个,你仍然可以添加integernumberusing +. 不好。因此,您可以通过使用函数按摩类型系统来对此处的参数强制执行类型安全。我只是将其称为警卫,而且您可以再次看到它不是特定于integers 的 - 您可以制作更多不透明的类型并再次使用它。

type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)

如果您尝试使用number

const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)

您会收到如下错误

Argument of type '10' is not assignable to parameter of type 'integer'.
  Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)

请注意,您没有在此处强制执行返回类型(因为您必须使用as integer),并且某些运算符(例如)/将返回浮点数,因此您可能仍希望进行运行时检查或将 a 添加Math.round到的专用版本中guard,但这至少会确保您没有尝试同时使用两种单独的数字类型 - 假设您有GBPUSD尝试添加它们,这可能不是您想要的。

于 2020-04-14T01:27:05.027 回答
3

AssemblyScript 支持整数值(及其 asm.js 后端)。您可以使用--jsFile.

要手动执行此操作,您可以通过添加将值强制为整数| 0

这提高了性能,因为浏览器引擎现在能够使用整数,这比操作中的浮点数更快。

假设你打算写:

function add(a: i32, b: i32) {
  return a + b
}

你应该这样写

type i32 = number
function add(a: i32, b: i32) {
  a = a | 0
  b = b | 0
  return a + b
}

或在 JavaScript 中(这是 asc --jsFile 生成的)

function add(a, b) {
  a = a | 0
  b = b | 0
  return a + b
}

对于类属性:

type i32 = number
class MyClass {
  a: i32 = a | 0
}
于 2020-12-24T09:53:48.857 回答
2

好吧,正如您所见,typescript 没有浮点数据类型,例如 javascript 语言。只有同时number覆盖所有intdouble;也许您必须创建一个接受数字的函数并检查它是否是 aintdouble,通过在错误/成功的情况下返回一些状态。像这样的东西作为你的类的方法:

function SetN(x:number) {
   var is_int = parseInt(x) === parseFloat(x);
   if(is_int) this.n = x;
   return is_int;
}

//..
y = 10.5;
if(SetN(y)) {
  //OK
} else {
   //error not set y isn't a int
}

注意:它不适用于10.0例如如果你真的不想要它,也许你必须将它转换为字符串并尝试找到一个..

于 2012-10-15T15:09:44.687 回答
1

int早期版本的 javascript(如果您愿意,可以使用 ECMAScript)中保留以供将来使用关键字。但它现在是一个有效的词(其中“现在”等同于“在最新规范中”)。

例如,在 262 中它仍然被保留,http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

int实现一个数据类型,但所有编译时类型检查和转换规则都可用,这将是对打字稿的一个很好的补充。

于 2012-10-15T15:30:34.133 回答
0

这是一个不进行装箱的数字接口的实现。我认为可以使用这种设计来创建 Integer 类型

于 2015-07-02T07:43:42.407 回答