typescript 类型问题

2019-01-25 14:46:19 +08:00
 azh7138m

泛型的参数是个泛型的话,要怎么写呢?

class Foo<T> {
  echo(bar: T) {
    return bar
  }
}

function box(klass) {
  return klass
}


const wraped = box(Foo)

想让 wraped 类型是

class <T> {
  echo(bar: T): void
}

Playground

相关 issue

Allow classes to be parametric in other parametric classes

3449 次点击
所在节点    问与答
22 条回复
momocraft
2019-01-25 15:11:17 +08:00
hkt..? TS 不直接支持,有一些民间的尝试,如 https://medium.com/@gcanti/higher-kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe (fp-ts io-ts 等的作者)
binux
2019-01-25 15:12:40 +08:00
function box(klass) {
return new klass()
}
wly19960911
2019-01-25 15:23:46 +08:00
强制类型转换
azh7138m
2019-01-25 15:26:34 +08:00
@wly19960911 要保留一个泛型参数,不要特化


@momocraft fp-ts 我知道,那这个 hkt 我要怎么构造? *->*->* 里面的第二个星应该是一个参数,不是一个特化后的类型


@binux 可我是要返回一个新的 class (
wly19960911
2019-01-25 15:28:40 +08:00
@azh7138m #4 是继承吗? 非声明的情况怎么保留一个泛型啊。。。
momocraft
2019-01-25 15:32:06 +08:00
momocraft
2019-01-25 15:33:01 +08:00
azh7138m
2019-01-25 15:33:31 +08:00
@wly19960911 是,所以我贴了一个 issue (
ts 源自 js 的语法,所以可以动态创建 class,但是这里类型我不会写了
对应实际问题 https://github.com/cssinjs/jss/issues/972
chengluyu
2019-01-25 15:37:19 +08:00
原生 TypeScript 你构造不出来的,用 Haskell 写的话是

forall a. a -> (forall b. b -> a)

这才是你想要的东西。
chengluyu
2019-01-25 15:39:57 +08:00
@momocraft 这样写的坏处就是你丧失了 TypeScript 编译器提供的类型推断……
momocraft
2019-01-25 15:42:46 +08:00
chengluyu
2019-01-25 15:46:47 +08:00
@azh7138m 可以是可以,毕竟 JavaScript 是动态类型语言,什么都能做。但是 TypeScript 的 type reducer 只能推断 rank 1 type,为了这个需求需要重写一个 rank-N type reducer,我觉得 TypeScript 官方不会给这个任务高优先级的……
wly19960911
2019-01-25 15:53:53 +08:00
看来这个东西是我理解错误了。

这个东西是函数式编程的? 这个意思看起来是 mixins 的味道,更像多继承的功能,实际上 js 原生就能实现的一个东西,但是我没有注意到 ts 能不能实现,丢人了。
wly19960911
2019-01-25 15:54:44 +08:00
@wly19960911 #13 并不是说不能实现,而是要充分利用 ts 能给的特性下去实现并且进行类型判断
chengluyu
2019-01-25 15:55:48 +08:00
@momocraft 我试了一下,其实是可以推断的,但是 TypeScript 的推断比较取巧。

见图: https://imgur.com/a/51faYNU
chengluyu
2019-01-25 15:58:50 +08:00
@wly19960911 其实就是在不 instantiate 一个 generic type 的情况下把这个 generic type 的名字用在 generic parameter 里。

我刚刚试了一下其实 TypeScript 可以推断,只要把 box 这个函数的类型标注出来就好了。
momocraft
2019-01-25 16:00:15 +08:00
@chengluyu
把 klass 原样返回是这样的,如果新的 class (我也不知道 box 本来打算做什么)不天然和 klass 同类型,至少我们还可以 as 过去 lol
chengluyu
2019-01-25 16:06:06 +08:00
@momocraft
只能问楼主想用 box 做什么了。
其实我觉得结合 TS 的 conditional type 和 infer 关键字应该能写出大部分类型来。
mooncakejs
2019-01-25 16:11:47 +08:00
有点没理解,是要:
class Foo<T> {
echo(bar: T) {
return bar
}
}
type Construct<T> = { new(...args: any[]): T }

function box<T>(klass: { new(): T }): T {
return new klass()
}
const wraped = box(Foo) as Foo<number> // 这一步只能 as

wraped.echo(1)
momocraft
2019-01-25 16:17:30 +08:00
@chengluyu 嗯,类型计算能做很多.. 我试过用 mapped type 写一个“完全的” Readonly,但有类型递归 (直接或间接递归)时就直接报错了。目前的版本是 https://gist.github.com/jokester/e6a4c11f4d2bb22fbbc48b547f49f980

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/530586

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX