Scala 代码片段到 TypeScript(如何转换抽象类型成员)

2024-02-06

我在 Scala 中有一小段值级别和类型级别列表

sealed trait RowSet {
  type Append[That <: RowSet] <: RowSet

  def with[That <: RowSet](that: That): Append[That]
}

object RowSet {

  case object Empty extends RowSet {
    type Append[That <: RowSet] = That

    override def with[That <: RowSet](that: That): Append[That] = that
  }

  case class Cons[A, B <: RowSet](head: A, tail: B) extends RowSet { self =>
    type Append[That <: RowSet] = Cons[A, tail.Append[That]]

    override def with[That <: RowSet](that: That): Append[That] = Cons(head, tail ++ that)
  }
}

现在,我正在尝试将其转换为 TypeScript。由于我们没有抽象类型成员 https://docs.scala-lang.org/tour/abstract-type-members.html功能,我似乎找不到不需要在某些时候进行类型转换的解决方案。

我目前在 TypeScript 中拥有的内容(也可以在操场 https://www.typescriptlang.org/play?#code/IYIwzgLgTsDGEAJYBthjAgSgewO4GUBTRAbwCgFKFRIZ4FcBLCACwB4AVF4RQgDwiEAdgBMMOAsQB8AClY8AXAi48AlEolEIZAL5kyEAJ4AHQggCCx06M4tGGfoNHi8WgDTLuvAcLFZX0ggAvBRUXPYIjr4YAMLYQmBsjEIAZoRQFh7JaRkAQlIIAPwIcQls5h6W1iJsuR4qEFIFSg0A3PooaBgAogC2xkaRPs7%20kqShlMYAriDIjLAMzOwNQ05%20mtJyXi1e6p48CORUxwhQxFNQQgjyEO3Henpknegl8YkVCLmr0aNaBVEjDbjY6wN7QKbwbBQGTTWbzU6EYAieLIQwIFiIkRKD6wuYLM5IlFoiDARjIJS5VSHCYnMBTUzQ1R3KiPY64%20FMVi2A4A9YBRpbRT7CB7UrvSpWXy1epeJrUk5UM4QC5XISEXCvBJbewAOgxSI8rF1JLJOs5LEFIuoGCqUrqwqkqhpDw6YIQfGCCDVGrFMgArB5vQg%20gNDE7QQlEGigl71ZqwDIAER2ROBuMhozht0AL09fDNSxkYaAA)

abstract class RowSet {
    abstract with<That extends RowSet>(that: That): RowSet
}

type Append<This extends RowSet, That extends RowSet> =
    This extends Cons<infer A, infer B> ? Cons<A, Append<B, That>> : That;

class Empty extends RowSet {
    public with<That extends RowSet>(that: That): That {
        return that;
    }
}

class Cons<A, B extends RowSet> extends RowSet {
    constructor(public readonly head: A, public readonly tail: B) {
        super();
    }

    public with<That extends RowSet>(that: That): Cons<A, Append<B, That>> {
        return new Cons(this.head, this.tail.with(that) as Append<B, That>)
    }
}

const x = new Cons(5, new Empty)    // Cons<number, Empty>
const y = new Cons("hi", new Empty) // Cons<string, Empty>
const z = x.with(y)                 // Cons<number, Cons<string, Empty>> 

我感兴趣的是我们是否可以避免在这里进行转换:

return new Cons(this.head, this.tail.with(that) as Append<B, That>)

看来 TypeScript 理解该值实际上是Append<B, That>因为它不允许投射到任何不同的东西,例如Append<B, B>或类似的东西。但因为我们使用with from abtract class RowSet我们最终得到Cons<A, RowSet>.

我们能否以不同的方式定义 RowSet,以便 TypeScript 在没有我们帮助的情况下正确推断所有内容?也许有不同的抽象类型成员转换方式(从 Scala 转换时)?


感谢 Oleg Pyzhcov 的评论,我能够在没有任何手动类型转换的情况下使其工作。 F-bounded 多态性被建议作为解决这个问题的一种方法,事实证明它确实有帮助

解决方案看起来像这样,不需要类型转换,一切都按预期工作

abstract class RowSet<T extends RowSet<T>> {
    abstract with<That extends RowSet<That>>(that: That): Append<T, That>
}

type Append<This extends RowSet<This>, That extends RowSet<That>> =
    This extends Cons<infer A, infer B> ? Cons<A, Append<B, That>> : That;

class Empty extends RowSet<Empty> {
    public with<That extends RowSet<That>>(that: That): That {
        return that;
    }
}

class Cons<A, B extends RowSet<B>> extends RowSet<Cons<A,B>> {
    constructor(public readonly head: A, public readonly tail: B) {
        super();
    }

    public with<That extends RowSet<That>>(that: That): Cons<A, Append<B, That>> {
        return new Cons(this.head, this.tail.with(that))
    }
}

const x = new Cons(5, new Empty)    // Cons<number, Empty>
const y = new Cons("hi", new Empty) // Cons<string, Empty>
const z = x.with(y)                 // Cons<number, Cons<string, Empty>> 

你可以检查一下

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 代码片段到 TypeScript(如何转换抽象类型成员) 的相关文章

  • 哪些 ORM 与 Scala 配合得很好? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 Object.entries() 时保留键类型

    这是我的问题的一个例子 ts 游乐场演示 https www typescriptlang org play code C4TwDgpgBAKg1hEUC8UDkAzA9ltUA 6ARgIYBOehaAJhBiQK4A2wA0omgFCc
  • 对于空列表,max() 应该返回什么?

    Got java util NoSuchElementException head of empty list所以我试着检查一下 但现在我明白了 info max of a few numbers FAILED info 0 did not
  • 将 Scala 库转换为 DLL (.NET)

    我正在尝试从 scala 类创建一个 Dll 我将 IntelliJ 与 SBT 一起使用 我已经找到了一种使用 ikvm converter 将 jar 文件转换为 Dll 的方法 现在的问题是 当我在 SBT 下使用 package 从
  • Scala:具有复杂结构的树插入尾递归

    我正在 scala 中创建自定义对象树 并且我的插入方法引发堆栈溢出 因为它不是尾递归 但是 我不太清楚如何使其尾递归 我见过使用 累加器 变量的相关示例 但它们要么是只能相乘和覆盖的整数之类的东西 要么是我在适应树时遇到困难的列表 这是我
  • “未知”与“任何”

    TypeScript 3 0 引入unknown根据他们的 wiki 输入 未知现在是保留类型名称 因为它现在是内置类型 根据您对未知的预期用途 您可能需要删除 完全声明 有利于新引入的未知类型 或者 将其重命名为其他名称 有什么区别unk
  • 打字稿 - 找不到导出

    我在模块 A 中有这个 Typescript 文件 somefile tsx import remAuto from tidee life theme 在模块 B 中 我导出了 index js 文件remAuto index js imp
  • Scala 中值类的隐式 Json 格式化程序

    我有许多值类组成了一个更大的对象案例类 final case class TopLevel foo Foo bar Bar final case class Foo foo String extends AnyVal final case
  • Scala 相当于 Java 的 Number

    我正在尝试为数值域类型构建类型层次结构 例如AYear is an Int 这是一个Number a Percentage is a Double 这是一个Number等等 我需要层次结构以便我可以调用toInt or toDouble关于
  • Scala Array.apply 有何魔力

    来自 scala 2 10 4 的 array scala Array定义为 final class Array T length Int extends java io Serializable with java lang Clonea
  • If 语句中的 Typescript 类型推断不能用作变量

    考虑以下示例 class A class B extends A foo return 6 const variable A new B const isValid variable instanceof B if isValid vari
  • “ReactNode”不是有效的 JSX 元素

    我有以下代码 代码沙箱 https codesandbox io s react typescript forked 50beyp file src App tsx import ComponentType ReactNode from r
  • 使用 Akka 玩 2.5 - 找不到参数超时的隐式值:akka.util.Timeout

    我正在尝试使用 Play 2 5 测试 Akka 但遇到了一个似乎无法解决的编译错误 我正在关注 Play 文档中的此页面 https playframework com documentation 2 5 x ScalaAkka http
  • 如何将 zingchart 实现到 Angular2 中

    我有一个现有的项目 我想在其上实施 zingcharts 我尝试了 3 个不同的教程 主要来自 https blog zingchart com 2016 07 19 zingchart and angular 2 charts back
  • Typescript 找不到模块

    我在 Typescript 的一个文件 upload ts 中有一个导出的模块 我无法在没有错误的情况下导入到另一个文件 application ts 中 另外 我无法导入 ExpressJS 这是Upload ts
  • 单击上一页的按钮路由到该页面后如何刷新页面

    我有 2 个页面 一个主页和一个页面 2 当我单击主页上的按钮时 它会路由到 page2 现在 单击主页上的按钮后 当我到达第 2 页时 它应该刷新 因为我的项目中存在一些缓存问题 我在ngoninit上添加了window location
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • TypeScript 代码上的 JSlint - 它还能教我编写更好的代码吗?

    在 TypeScript 生成的代码上使用 JSlint 还能教我编写更好的代码吗 如果是 您能提供一两个例子吗 Thanks 没有 由于生成的 javascript 在不良打字稿 良好打字稿之间是一致的 例如缺少分号 对于打字稿 有一个
  • 在 Angular 6 服务中获取当前路由参数的最佳方法是什么?

    我试图找出在 Angular 6 中获取当前路由参数的最佳方法是什么 目前我必须通过ActivatedRoute到服务的方法作为参数 然后在服务中使用它 export class MainComponent constructor priv
  • TypeScript 中的可变参数方法至少需要一个参数

    我有一个像这样的方法 getValues args Array

随机推荐