我正在尝试使用TypeScript,并且在创建一个具有应该是整数的"ID"字段的类的过程中,我有点困惑.
首先,在使用TypeScript插件的Visual Studio 2012中,我在intelliSense类型列表中看到"int".但是我得到一个编译错误,说"当前范围中不存在名称'int'".
我查看了语言规范,只看到以下原始类型:number,string,boolean,null和undefined.没有整数类型.
所以,我有两个问题:
我应该如何向我的班级用户表明某个特定字段不仅仅是一个"数字"而是一个整数(从不是浮点数或十进制数)?
如果它不是有效类型,为什么我会在intellisense列表中看到"int"?
更新:到目前为止我得到的所有答案都是关于JavaScript如何没有int类型,在运行时很难强制执行int类型......我知道这一切.我问是否有一种TypeScript方式为我的类用户提供一个注释,该字段应该是一个整数.也许某些特定格式的评论?
Diu*_*lei 86
我认为没有直接的方法来指定数字是整数还是浮点数.在TypeScript规范第3.2.1节中,我们可以看到:
"... Number原语类型对应于类似命名的JavaScript原语类型,表示双精度64位格式IEEE 754浮点值......"
我认为int是Visual Studio intelliSense中的一个错误.正确的是number.
Fen*_*ton 24
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...
Run Code Online (Sandbox Code Playgroud)
Sho*_*hou 16
这是我在 Google 上的最佳结果,所以我想我应该提供我找到的解决方案。
bigint现在是 2020 年并bigint已被接受,值得一提。您可以简单地执行以下操作。请注意,bigint与number.
const myNumber: bigint = 10n
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用名义类型,但它可以说不太符合人体工程学,我不确定它是否比 快bigint,但该模式确实可以推广到任何类型,而不仅仅是number. TypeScript 对此没有“一流”的支持,所以你必须做一个厚颜无耻的黑客。有一个名为的库newtype-ts,其中包含常见类型,Integer因此您可能只想使用它,但我将在下面解释其工作原理。
首先,我们定义integer类型。
const TAG = Symbol()
type integer = number & { readonly [TAG]: unique symbol }
Run Code Online (Sandbox Code Playgroud)
在TAG确保我们有一个独特的价值,使我们不小心使一个物体使用相同的密钥,并且我们做该领域的独特符号也出于同样的原因。现在,您的整数实际上不会有这个对象字段,但这很好。
有了这个,您仍然可以添加integer到number使用+. 不好。因此,您可以通过使用函数按摩类型系统来对此处的参数实施类型安全。我只想称它为守卫,正如你所看到的,它不是特定于integers 的——你可以制作更多不透明的类型并再次使用它。
type guard = <A>(f: (...ns: Array<A>) => A, ...ns: Array<A>) => A
const guard: guard = (f, ...ns) => f(...ns)
Run Code Online (Sandbox Code Playgroud)
如果您尝试使用 number
const bad: integer = guard((a, b) => a + b as integer, myCoolInteger, 10)
Run Code Online (Sandbox Code Playgroud)
你会得到如下错误
Argument of type '10' is not assignable to parameter of type 'integer'.
Type '10' is not assignable to type '{ readonly [TAG]: unique symbol; }'.(2345)
Run Code Online (Sandbox Code Playgroud)
请注意,您没有在此处强制执行返回类型(因为您必须使用as integer),并且某些运算符/会返回浮点数,因此您可能仍希望进行运行时检查或将 a 添加Math.round到 的专用版本guard,但这至少会确保你不尝试使用两个单独的数字类型一起-想象一下,你有GBP和USD,并尝试添加这些,那很可能不是您所希望的。
像JavaScript中一样,没有integer或float只能number键入TypeScript。但是,如果您想告诉程序员您希望integer输入类型,则可以尝试使用类型别名,例如
type integer = number;
type float = number;
// example:
function setInt(id: integer) {}
Run Code Online (Sandbox Code Playgroud)
但这仍然是number类型,您可以得到float。
文档描述的一部分:
“别名实际上并没有创建一个新类型-它创建了一个新名称来引用该类型。别名基本体并不是非常有用,尽管它可以用作文档形式。”
在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;
Run Code Online (Sandbox Code Playgroud)
这样做可以使您在代码中更加明确地了解属性的类型,并且编译器不允许您在不进行强制转换的情况下分配原始值。这不会产生任何其他.js输出,您仍然可以使用和使用这些值作为它们基于的任何类型。在此示例中,我使用数字,但是您也可以在字符串和其他类型上使用。
在此示例中,您仍然可以诱使编译器接受不是Int或Id的内容,但是如果您尝试将1.45分配为Int或类似的内容,它应该会跳出。您还可以选择创建用于创建值以提供运行时验证的辅助函数。
创建“标记”类型的方法有多种。这是一篇好文章:https : //michalzalecki.com/nominal-typing-in-typescript/
| 归档时间: |
|
| 查看次数: |
61064 次 |
| 最近记录: |