typescript 你如何指定一个类属性是一个整数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12897742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you specify that a class property is an integer?
提问by Josh
I'm experimenting with TypeScript, and in the process of creating a class with an "ID" field that should be an integer, I have gotten a little confused.
我正在试验 TypeScript,在创建一个“ID”字段应该是整数的类的过程中,我有点困惑。
First off, in Visual Studio 2012 with the TypeScript plugin, I see "int" in the intelliSense list of types. But I get a compile error that says "the name 'int' does not exist in the current scope".
首先,在带有 TypeScript 插件的 Visual Studio 2012 中,我在类型的 intelliSense 列表中看到了“int”。但是我收到一个编译错误,提示“当前作用域中不存在名称‘int’”。
I reviewed the language specs and see only the following primitive types: number, string, boolean, null, and undefined. No integer type.
我查看了语言规范,只看到了以下原始类型:数字、字符串、布尔值、空值和未定义。没有整数类型。
So, I'm left with two questions:
所以,我有两个问题:
How should I indicate to users of my classthat a particular field is not just a "number" but an integer (and never a floating point or decimal number)?
Why do I see "int" in the intellisense list if it's not a valid type?
我应该如何向我的班级的用户表明特定字段不仅仅是一个“数字”而是一个整数(而不是浮点数或十进制数)?
如果不是有效类型,为什么我会在智能感知列表中看到“int”?
Update: All the answers I've gotten so far are about how JavaScript doesn't have an int type, it would be hard to enforce an int type at runtime... I know all that. I am asking if there is a TypeScript way to provide an annotation to users of my class that this field should be an integer. Perhaps a comment of some particular format?
更新:到目前为止我得到的所有答案都是关于 JavaScript 没有 int 类型,在运行时很难强制执行 int 类型......我知道这一切。我在问是否有一种 TypeScript 方法可以向我的班级的用户提供该字段应该是整数的注释。也许是某种特定格式的评论?
回答by Diullei
I think there is not a direct way to specify whether a number is integer or floating point. In the TypeScript specification section 3.2.1 we can see:
"...The Number primitive type corresponds to the similarly named JavaScript primitive type and represents double-precision 64-bit format IEEE 754 floating point values..."
I think
int
is a bug in Visual Studio intelliSense. The correct isnumber
.
我认为没有直接的方法来指定一个数字是整数还是浮点数。在 TypeScript 规范第 3.2.1 节中我们可以看到:
“...... Number 原始类型对应于类似命名的 JavaScript 原始类型,并表示双精度 64 位格式 IEEE 754 浮点值......”
我认为
int
是 Visual Studio 智能感知中的一个错误。正确的是number
。
回答by Fenton
TypeScript is a superset of JavaScript, which doesn't have a concept of an int. It only has the concept of a number, which has a floating point.
TypeScript 是 JavaScript 的超集,它没有 int 的概念。它只有一个数字的概念,它有一个浮点数。
Philosophically, the amount of work the compiler would have to do to enforce only whole numbers for a TypeScript int type could potentially be massive and in some cases it would still not be possible to ensure at compile time that only whole numbers would be assigned, which is why it isn't possible to reliably add an int
to TypeScript.
从哲学上讲,编译器为 TypeScript int 类型仅强制执行整数的工作量可能是巨大的,并且在某些情况下,仍然无法确保在编译时只分配整数,这这就是为什么不可能可靠地int
向 TypeScript添加。
When you initially get intelliSense in Visual Studio, it isn't possible for the tooling to determine what to supply, so you get everything, including int - but once you are dealing with something of a known type, you'll get sensible intelliSense.
当您最初在 Visual Studio 中获得智能感知时,工具无法确定要提供的内容,因此您可以获得所有内容,包括 int - 但是一旦您处理已知类型的内容,您将获得明智的智能感知。
Examples
例子
var myInt: number;
var myString: string;
myInt. // toExponential, toFixed, toPrecision, toString
myString. // charAt, charCodeAt, concat, indexOf, lastIndexOf, length and many more...
回答by Mariusz Charczuk
There is no integer
or float
but number
type in TypeScript like in JavaScript.
But if you want tell programmer that you expect integer
type you can try to use Type Aliaseslike
在 TypeScript 中没有integer
or float
butnumber
类型,就像在 JavaScript 中一样。但是,如果你想告诉程序员,你希望integer
键入您可以尝试使用类型别名像
type integer = number;
type float = number;
// example:
function setInt(id: integer) {}
but this is still number
type and you can get float
.
但这仍然是number
类型,您可以获得float
.
Part of description from documentation:
"Aliasing doesn't actually create a new type - it creates a new name to refer to that type. Aliasing a primitive is not terribly useful, though it can be used as a form of documentation."
文档中的部分描述:
“别名实际上并没有创建新类型 - 它创建了一个新名称来引用该类型。别名原语并不是非常有用,尽管它可以用作一种文档形式。”
回答by bingles
In TypeScript you can approximate what is sometimes called an opaque type using a marker.
在 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;
Doing this allow you to be more explicit in your code as to what types your properties expect, and the compiler won't allow you to assign a primitive value without a cast. This doesn't produce any additional .js output, and you can still consume and use the values as whatever types they are based on. In this example I'm using numbers, but you can use on strings and other types as well.
这样做可以让您在代码中更明确地了解属性期望的类型,并且编译器不允许您在没有强制转换的情况下分配原始值。这不会产生任何额外的 .js 输出,您仍然可以使用这些值作为它们所基于的任何类型。在本例中,我使用的是数字,但您也可以在字符串和其他类型上使用。
You can still trick the compiler into accepting something that isn't an Int or an Id in this example, but it should jump out if you were trying to assign 1.45 as Int or something like that. You also have the option of creating helper functions that you use to create your values to provide runtime validation.
在这个例子中,你仍然可以欺骗编译器接受不是 Int 或 Id 的东西,但如果你试图将 1.45 分配为 Int 或类似的东西,它应该会跳出来。您还可以选择创建用于创建值以提供运行时验证的辅助函数。
There's a number of different ways you can create "marked" types. Here's a good article: https://michalzalecki.com/nominal-typing-in-typescript/
您可以通过多种不同的方式创建“标记”类型。这是一篇好文章:https: //michalzalecki.com/nominal-typing-in-typescript/
回答by Shou
This is the top result on Google for me so I figure I should provide the solutions I found.
这是我在 Google 上的最佳结果,所以我想我应该提供我找到的解决方案。
Using bigint
使用 bigint
Now that it's 2020 and bigint
has been accepted, it deserves a mention. You can simply do the below. Beware that bigint
s come with a bigger performance impact compared to a number
.
现在是 2020 年并bigint
已被接受,值得一提。您可以简单地执行以下操作。请注意,bigint
与number
.
const myNumber: bigint = 10n
Using a nominal type / tagged type / opaque type
使用名义类型/标记类型/不透明类型
An alternative is to use a nominal type, but it's arguably less ergonomic and I'm not sure if it's any faster than bigint
, but the pattern does generalise to any type, not just number
. TypeScript doesn't have "first-class" support for this so you have to do a cheeky hack. There's a library for this called newtype-ts
that includes common types like Integer
so you might just want to just use that, but I'll explain the workings below.
另一种方法是使用名义类型,但它可以说不太符合人体工程学,我不确定它是否比 快bigint
,但该模式确实可以推广到任何类型,而不仅仅是number
. TypeScript 对此没有“一流”的支持,所以你必须做一个厚颜无耻的黑客。有一个名为的库newtype-ts
,其中包含常见类型,Integer
因此您可能只想使用它,但我将在下面解释其工作原理。
To start out with we define the integer
type.
首先,我们定义integer
类型。
const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }
The TAG
ensures we have a unique value so that we don't accidentally make an object with the same key, and we make the field a unique symbol too for the same reason. Now, your integer won't actually have this object field but that's fine.
在TAG
确保我们有一个独特的价值,使我们不小心使一个物体使用相同的密钥,并且我们做该领域的独特符号也出于同样的原因。现在,您的整数实际上不会有这个对象字段,但这很好。
With this you can still add integer
to number
using +
. Not good. So you can enforce type safety on the arguments here by massaging the type system with a function. I'm just gonna call it guard, and again as you can see it isn't specific to integer
s – you could make more opaque types and use this again.
有了这个,您仍然可以添加integer
到number
使用+
. 不好。因此,您可以通过使用函数按摩类型系统来对此处的参数实施类型安全。我只想称它为守卫,正如你所看到的,它不是特定于integer
s 的——你可以制作更多不透明的类型并再次使用它。
type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)
If you try to call that with a number
如果您尝试使用 number
const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)
you'll get an error like below
你会得到如下错误
Argument of type '10' is not assignable to parameter of type 'integer'.
Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)
Note that you aren't enforcing the return type here (because you have to use as integer
) and some operators like /
will return floating point numbers so you probably still want to do runtime checks or add a Math.round
to a specialised version of guard
, but this will at least ensure you're not trying to use two separate numeric types together – imagine you have GBP
and USD
and try to add those, that would likely not be what you intended.
请注意,您没有在此处强制执行返回类型(因为您必须使用as integer
),并且某些运算符/
会返回浮点数,因此您可能仍希望进行运行时检查或将 a 添加Math.round
到 的专用版本guard
,但这至少会确保你不尝试使用两个单独的数字类型一起-想象一下,你有GBP
和USD
,并尝试添加这些,那很可能不是您所希望的。
回答by Hyman
Well, as you have seen, typescript haven't float data type such as javascript language. Only have the number
that cover all int
and double
at same time; maybe you must make a function that take a number and check it if it's a int
or double
, by returning some state in case error/success. Something like this as method of your class:
好吧,正如您所见,打字稿没有浮动数据类型,例如 javascript 语言。只有拥有number
覆盖所有int
并double
在同一时间; 也许您必须创建一个函数,该函数接受一个数字并检查它是否是 aint
或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
}
Note: it doest not works for 10.0
e.g. If you want no really it, maybe you must conver it to string and try to find a .
.
注意:它不适用于10.0
例如如果你真的不想要它,也许你必须将它转换为字符串并尝试找到一个.
.
回答by Arek Bal
int
was reserved for future use keyword in earlier versions of javascript(ECMAScript if you prefer). But it is a valid word now (where "now" equates to "in the latest spec").
int
在早期版本的 javascript中保留以供将来使用关键字(如果您愿意,可以使用 ECMAScript)。但它现在是一个有效词(其中“现在”等同于“在最新规范中”)。
For instance, in 262 it was still reserved, http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
比如262还是保留的,http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
It would make nice addition to typescript to have an int
datatype implemented but with all compile-time type checking and casting rules available.
int
实现数据类型但所有编译时类型检查和转换规则都可用,这将是打字稿的一个很好的补充。
回答by James Wakefield
Here is an implementation of number interfacethat doesn't do boxing. I think it would be possible to use this design to create an Integer type