所以假设我有这样的事情:
type Id<T> = T;
const f = <B>(a: Id<B>, b: B): [Id<B>, B] => [a, b];
但我想扩展 f
以便能够使用其他依赖类型
type List<T> = T[];
我怎样才能实现类似的目标
const f = <A, B>(a: A<B>, b: B): [A<B>, B] => [a, b];
f<Id, number>(1, 2) // evaluates to [1,2]
f<List, number>([1], 2) // evaluates to [[1],2]
没有打字稿抱怨 A
不是通用的吗?还是传递给泛型的类型必须是平面类型?
答案 0 :(得分:0)
不幸的是,TypeScript 不直接支持您想要 A
的那种更高种类的类型 (HKT)。并且您不能在不立即为某些 Id
指定其类型参数(如 Id<T>
)的情况下引用 T
。请参阅 microsoft/TypeScript#1213 以获取对更高级类型的长期开放功能请求。该问题确实列出了一些可以在 TypeScript 中模拟/模拟 HKT 的方法,但还不够好,我真的推荐它。
例如,您可以执行以下操作,通过 merging it into an interface declaration 显式注册您关心的每个更高级的类型:
type Id<T> = T;
interface HKTRegistry<T> { Id: Id<T> };
type List<T> = T[];
interface HKTRegistry<T> { List: List<T> }
然后你可以像这样使用它:
const f = <A extends HKT, B>(a: Specify<A, B>, b: B): [Specify<A, B>, B] => [a, b];
const id = f<"Id", number>(1, 2);
const hmm = f<"List", number>([1], 2);
其中 HKT
和 Specify
的定义如下:
type HKT = keyof HKTRegistry<any>
type Specify<H extends HKT, T> = HKTRegistry<T>[H];
但它很笨重,并且不能捕获 constrained 类型参数之类的东西,而且很难以这种方式推断 HKT。正如我所说,它并不是我真正推荐用于任何生产代码的地方。