我如何在打字稿中表达这一点?

bch*_*rny 15 haskell types scala typescript purescript

假设我有一个界面A:

interface A {
  foo: number
  bar: string
}
Run Code Online (Sandbox Code Playgroud)

我有一个通用类型Option:

type Option<T> = {
  map: () => T
}
Run Code Online (Sandbox Code Playgroud)

然后我BA和创建一个新的界面Option:

interface B {
  foo: Option<number>
  bar: Option<string>
}
Run Code Online (Sandbox Code Playgroud)

如何让这个操作更通用?IE浏览器.我想要的API是:

type B = Lift<A>
Run Code Online (Sandbox Code Playgroud)

在哪里Lift自动将每个成员映射A到一个Option.请注意,A可以包含任意类型的任意数量的成员.

我该如何实施Lift?如果在TypeScript中无法做到这一点,那么有没有人有Scala/Haskell解决方案?

pat*_*rit 9

您正在寻找更高级的类型.这是在Scala中:

trait FooBar[M[_]] {
  val foo: M[Integer]
  val bar: M[String]
}

type Identity[X] = X
type A = FooBar[Identity]
type B = FooBar[Option]
Run Code Online (Sandbox Code Playgroud)

您可以使用任何二阶类型,例如:

type C = FooBar[List]
Run Code Online (Sandbox Code Playgroud)

但这些不会编译:

// type S = FooBar[String] ---> String is a first-order type
// type M = FooBar[Map]    ---> Map[K, V] is a third-order type
Run Code Online (Sandbox Code Playgroud)

不幸的是,这还没有成为TypeScript,但它有一个未解决的问题:https://github.com/Microsoft/TypeScript/issues/1213


Leo*_*ler 5

好消息:有了TypeScript 2.1.0,现在可以通过Mapped Types实现

type Option<T> = { map() => T };
type OptionsHash<T> = { [K in keyof T]: Option<T[K]> };
Run Code Online (Sandbox Code Playgroud)
function optionsFor<T>(structure: T): OptionsHash<T> { ... };

let input = { foo: 5, bar: 'X' };
let output = optionsFor(input);
// output is now typed as { foo: { map: () => number }, bar: { map: () => string } }
Run Code Online (Sandbox Code Playgroud)

相反也可能:

function retreiveOptions<T>(hash: OptionsHash<T>): T { ... };

let optionsHash = {
    foo: { map() { return 5; } },
    bar: { map() { return 'x'; } }
};
let optionsObject = retreiveOptions(optionsHash);
// optionsObject is now typed as { foo: number, bar: string }
Run Code Online (Sandbox Code Playgroud)