【问题标题】:Typescript type to prevent division by 0防止被0除的打字稿类型
【发布时间】:2021-12-05 07:12:42
【问题描述】:

我正在使用打字稿创建一个用于训练目的的计算系统,但在除法期间出现打字错误。

你知道怎么解决吗?

type Variable = {
    value: number
    resolve: () => number
}

type NoZeroVariable = {
    value: Omit<number, 0>
    resolve: () => Omit<number, 0>
}

// then when I try to resolve the operation
a.resolve() / b.resolve()

我收到此错误: The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2363)

【问题讨论】:

  • 我认为您遗漏了算术代码。 abyour example 中是 undefined,并且没有执行任何算术的代码。
  • Omit&lt;number, 0&gt; 不会将0 从所有可能的数字中排除。请查看Omit 文档typescriptlang.org/docs/handbook/…
  • 我想你想用Exclude而不是Omit
  • TypeScript 中没有否定类型;您可以过滤工会,但number 不是工会。 TypeScript 中没有与非零数字完全对应的特定类型。你可以像 Captainyossarian 那样写一个通用的约束,但这意味着所有触及它的东西也需要是通用的。

标签: typescript types type-inference divide-by-zero


【解决方案1】:

这里有非常简单的实现:

type NonZero<T extends number> = T extends 0 ? never : number extends T ? never : T


const division = <
    A extends number,
    B extends number
>(a: A, b: NonZero<B>) =>
    a / b

division(10, 2) // ok
division(10, 0) // error


const higherOrderFunction = (b: number) => division(10, b) // error, b is not verified


`NonZero` - expects a number. If number is has a literal representation like `1`,`2` or any other literal it returns this number, otherwise (if it is `0` or `number`) it returns `never`

Playground

b 应该只是文字数字。它不能是number 类型的变量,因为您不知道运行时的值。

让我们继续你的例子:

type Variable<N extends number> = {
  value: N
  resolve: () => number
}


type NonZero<T extends number> = T extends 0 ? never : number extends T ? never : T


const variableDivision = <
  Num1 extends number,
  Num2 extends number,

  >(a: Variable<Num1>, b: Variable<NonZero<Num2>>) =>
  a.resolve() / b.resolve()

variableDivision({ value: 42, resolve: () => 42 }, { value: 42, resolve: () => 0 }) // ok
variableDivision({ value: 42, resolve: () => 42 }, { value: 0, resolve: () => 0 }) // expected error

TypeScript 中不可能像 F# 那样重载除法运算符 /

因此,您需要创建一个额外的除法函数。

Num2 是从b 变量推断出的数字。如果是0,则NonZero 返回never,整个b 参数变为Variable&lt;never&gt;。因为never 是不可代表的,你得到了错误。 Playground

【讨论】:

  • 感谢您的回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2017-11-03
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2020-10-12
相关资源
最近更新 更多