如何指定类属性是整数?

时间:2012-10-15 14:25:58

标签: typescript

我正在尝试使用TypeScript,在创建一个应该是整数的“ID”字段的类的过程中,我有点困惑。

首先,在使用TypeScript插件的Visual Studio 2012中,我在intelliSense类型列表中看到“int”。但是我得到一个编译错误,说“当前范围中不存在名称'int'。”

我查看了语言规范,只看到以下原始类型:number,string,boolean,null和undefined。没有整数类型。

所以,我有两个问题:

  1. 我应该如何向我班级的用户表明特定字段不仅仅是一个“数字”而是一个整数(绝不是浮点数或十进制数)?

  2. 为什么我会在intellisense列表中看到“int”,如果它不是有效类型?

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

8 个答案:

答案 0 :(得分:79)

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

      

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

  2. 我认为int是Visual Studio intelliSense中的一个错误。正确的是number

答案 1 :(得分:22)

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

哲学上,编译器必须做的工作量才能强制执行TypeScript int类型的整数,这可能是巨大的,在某些情况下,仍然无法确保在编译时只有整数就是已分配,这就是无法将int可靠地添加到TypeScript的原因。

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

实施例

var myInt: number;
var myString: string;

myInt. // toExponential, toFixed, toPrecision, toString
myString. // charAt, charCodeAt, concat, indexOf, lastIndexOf, length and many more...

答案 2 :(得分:5)

Type DEBUG output/shellwriter.c:22: Writing "windscribe login" to shell. DEBUG output/shellwriter.c:27: File successfully opened. DEBUG output/shellwriter.c:30: Writing to shell. DEBUG output/shellwriter.c:30: Writing to shell. Windscribe Password: Windscribe Username: 中没有integerfloat类型,就像JavaScript中的number类型。 但是,如果您想告诉程序员您希望使用integer类型,则可以尝试像这样使用Type Aliases

type integer = number;
type float = number;

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

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

文档中的部分说明:
“别名实际上并不会创建新的类型-它会创建一个新名称来引用该类型。别名的基本含义并不是很有用,尽管它可以用作文档形式。” < / p>

答案 3 :(得分:5)

对于我来说,这是Google上的最佳结果,因此我认为我应该提供找到的解决方案。

使用bigint

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

const myNumber: bigint = 10n


使用名义类型/标记类型/不透明类型

一种替代方法是使用名义类型,但可以说它的人体工程学性较低,我不确定它是否比bigint快,但是该模式确实可以推广到任何类型,而不仅仅是number 。 TypeScript没有对此的“一流”支持,因此您必须做一个厚脸皮的黑手。有一个名为newtype-ts的库,其中包含诸如Integer之类的常见类型,因此您可能只想使用它,但我将在下面解释其工作原理。

首先,我们定义integer类型。

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

TAG确保我们具有唯一值,以免我们意外地使对象具有相同的键,并且出于相同的原因,我们也使字段成为唯一的符号。现在,您的整数实际上将没有此对象字段,但这很好。

您仍然可以使用integernumber添加到+。不好。因此,您可以在此处通过对类型系统进行函数按摩来对参数执行类型安全性。我只是称呼它为守卫,正如您所看到的,它并不是特定于integer的–您可以创建更多不透明的类型并再次使用。

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),并且某些操作符(例如/)将返回浮点数,因此您可能仍希望进行运行时检查或将Math.round添加到guard的专用版本中,但这至少可以确保您不会尝试同时使用两个单独的数字类型–假设您有GBP和{{1} },然后尝试添加这些,而这可能不是您想要的。

答案 4 :(得分:2)

好吧,正如你所看到的,typescript没有浮动数据类型,如javascript语言。只有同时涵盖所有numberint的{​​{1}};也许你必须创建一个带数字的函数,并检查它是double还是int,通过返回一些状态以防错误/成功。像这样的方法:

double

注意:它不适用于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

答案 5 :(得分:1)

在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或类似的东西,它应该跳出来。您还可以选择创建辅助函数,用于创建值以提供运行时验证。

您可以通过多种不同方式创建&#34;标记&#34;类型。这是一篇好文章:https://michalzalecki.com/nominal-typing-in-typescript/

答案 6 :(得分:0)

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

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

如果实现了int数据类型,并且可以使用所有编译时类型检查和转换规则,那么它将很好地添加到typescript中。

答案 7 :(得分:0)

这是一个不做拳击的implementation of number interface。我认为可以使用这种设计来创建一个Integer类型