TypeScript 添加数值 predicate 表达式文字类型

rnmwe5a2  于 6个月前  发布在  TypeScript
关注(0)|答案(3)|浏览(49)

建议

🔍 搜索词

在创建此问题之前,您搜索的关键词列表。请在这里写下它们,以便其他人能更容易地找到此建议并提供反馈。
数字模板字面量类型
模板数字字面量类型
表达式数字字面量类型
有界数字

✅ 可实现性检查清单

我的建议符合以下准则:

  • [✅] 这不会对现有的TypeScript/JavaScript代码造成破坏性的更改
  • [✅] 这不会改变现有JavaScript代码的运行时行为
  • [✅] 可以在不根据表达式的类型发出不同的JS的情况下实现
  • [✅] 这不是一个运行时特性(例如库功能、具有JavaScript输出的非ECMAScript语法、新的JS语法糖等)
  • [✅] 此功能将与 TypeScript's Design Goals 的其他部分一致。

⭐ 建议

我希望看到数字表达式字面量类型。就像字符串模板字面量类型一样,但适用于数字。但是,由于数字是通过表达式计算的,因此将其与计算表达式匹配会更有帮助。

📃 动机示例

Typescript允许您像这样定义模板字符串字面量类型:

type OddNumberString = `${number}${1|3|5|7|9}`;

但不能为实数做同样的事。
如果确实可以声明带有表达式字面量类型的数字:

type OddNumber = n`(number+1) % 2 === 0`;
type EvenNumber = n`number % 2 === 0`;

它将匹配如下:

const odd1: OddNumber = 6; // error
const odd2: OddNumber = 5: // succeed

类型系统只需计算表达式并检查结果是否应等于true以匹配数字。
`n``` 仅允许数字、位和逻辑运算符:

  • +
  • -
  • *
  • /
  • %
  • **
  • >
  • <
  • ==
  • ===
  • <=
  • >=
  • ||
  • &&
  • |
  • &
  • ^

允许使用Math函数也可以做到,但不是必须的。
您还可以将其与扩展三元运算符一起使用:

type IsOddNumber<T extends number> = T extends n`(number+1) % 2 === 0` ? true : false;
fcg9iug3

fcg9iug31#

#26382 和或 #15645
我不确定这里的语法如何理解。它类似于一个带标签的模板字面量,其中 n 是某个我不知道如何理解的功能,或者你是如何在那里使用字符串 number 的。除了语法之外,我想你是想表达一种类型,其中所有值 x 都属于该类型,使得 typeof x === "number"f(x) 为真,其中 f(x) 是某种 predicate ,如 (x + 1)%2 === 0(对于 OddNumber)或 x > 0(对于 NaturalNumber,尽管通常不会说 0.5 是自然数)。这是公平的评估吗?
我不认为这是一个真正的实际应用场景。理想情况下,应该有一些例子说明为什么缺乏这种功能是一个痛点。比如,“如果编译器能捕获人们将负数或可能为负数传递给 Math.sqrt() 的常见错误就好了”。当然,我不认为这实际上是一个常见的错误,但如果它是,那么这种类型的用处就会很大。所以如果它不是防止 $sqrt{-1}$ 或 NaN 怪物的问题,那它又是什么呢?

yzckvree

yzckvree2#

关于使用案例,我也非常好奇。

vom3gejh

vom3gejh3#

@jcalz :
语法显然是一个建议。如果你认为另一个应该更清晰,我随时欢迎你提出。
对于自然数,感谢你指出不完整的定义,这里有一个有效的定义:

type NaturalNumber = n`(number === number | 0) && number>0`;

至于其他用例:

  • 范围数字类型可以用来表示特定领域的数字。最明显的用例是日期或时间:
const midnight: Bounded<0,23> = 0; // OK
const invalid: Bounded<0,23> = 25; // Error

但也可以表示RGB值:

type RGB = {
 r : Bounded<0,255>
 g: Bounded<0,255>
 b: Bounded<0,255>
};
const blue : RGB = { r: 0, g: 0, b: 255 };
const invalid: RGB = { r: 0, g: 0, b: 256 };

范围是非常明显的用例。这个提案主要是为了支持这个用例,但也允许更多的像自然数或者非浮点数。
其他语言如ADA只支持范围(还有模数类型,但JavaScript没有这个概念)。
以下是其他用例:

  • 二进制数(0或1)
  • 增量范围(例如:[0, 0.2, 0.4, 0.6, 0.8, 1],参见 ADA )

在数学、科学、数据科学或IA领域,能够静态约束作为输入的数字可以防止错误。
我知道IA不是JavaScript的主要关注点,但一些社区在使用(TensorFlow等),对数值计算有更好的TypeScript支持将是一个加分项。

相关问题