[英]Typescript equivalent for functional compose for multiple nested generics
Sometimes I do a lot of operations on a type in order to create a new one, ie:有时我对一种类型进行大量操作以创建一个新类型,即:
type Complex = Omit<Merge<Interface1, {modifiedField: false}>, 'omitted field'>
Is there any equivalent of a functional compose
or pipe
functions so that creating such a type would more readable, ie:是否有功能compose
或pipe
功能的等价物,以便创建这样的类型更具可读性,即:
type Complex = Pipe<Interface1,
Merge<{modified: false}>,
Omit<'omitted field'>
>
No, the language doesn't have higher-order type manipulation of the kind needed for this to work.不,该语言没有运行所需类型的高阶类型操作。 The closest I can imagine is to drop from the type level to the value level, abuse the recent support for higher order function inference from generic functions , and then move back up to the type level.我能想象的最接近的是从类型级别下降到值级别,滥用最近对泛型函数的高阶函数推断的支持,然后又回到类型级别。 It's not pretty and you end up with a little useless runtime code to boot.它并不漂亮,并且您最终会得到一些无用的运行时代码来启动。
Here's what I mean.这就是我的意思。 I'm assuming you have these definitions:我假设你有这些定义:
interface Interface1 {
a: string;
"omitted field": boolean;
}
type Merge<T, U> = T & U;
type ManualComplex = Omit<Merge<Interface1, { modifiedField: false }>, 'omitted field'>
/* type ManualComplex = {
a: string;
modifiedField: false;
} */
Then here's the hoop-jumping with values I'm talking about:然后这是我正在谈论的价值的跳圈:
declare const CurriedOmit: <K extends PropertyKey>() => <T>(t: T) => Omit<T, K>;
declare const CurriedMerge: <U>() => <T>(t: T) => Merge<T, U>;
declare const Id: <T>() => T
I'm pretending that there's a curried Omit
and Merge
, as well as an Id
.我假装有一个咖喱Omit
和Merge
,以及一个Id
。 Then we can pretend that there's a pipe()
function that applies these in order:然后我们可以假设有一个pipe()
函数按顺序应用这些:
// there may be some variadic pipe but for now let's do this:
declare const pipe: {
<A>(a: A): A;
<A, B>(a: A, b: (a: A) => B): B;
<A, B, C>(a: A, b: (a: A) => B, c: (b: B) => C): C;
<A, B, C, D>(a: A, b: (a: A) => B, c: (b: B) => C, d: (c: C) => D): D;
}
Finally I write some actual runtime code that fools the compiler into evaluating the type you want, although at runtime the code will short-circuit to true
(which is good because if it were to actually call the non-existent pipe()
function you'd get some yucky runtime error):最后,我编写了一些实际的运行时代码来欺骗编译器来评估您想要的类型,尽管在运行时代码将短路为true
(这很好,因为如果它实际上调用不存在的pipe()
函数,您d 得到一些令人讨厌的运行时错误):
const complex = (true as false) || pipe(
Id<Interface1>(),
CurriedMerge<{ modifiedField: false }>(),
CurriedOmit<'omitted field'>()
);
Now that the compiler thinks it has a value complex
, we can get Complex
as typeof complex
:现在编译器认为它有一个值complex
,我们可以得到Complex
作为typeof complex
:
type Complex = typeof complex;
/* type Complex = {
a: string;
modifiedField: false;
} */
Yay, it's the same type as ManualComplex
.是的,它与ManualComplex
类型相同。 😺🌹 Is it worth it? 😺🌹值得吗? No. 😿🥀 Oh well, best I can do.不。😿🥀 哦,我能做的最好。 I'd definitely stick with the non-piped version you started with.我肯定会坚持使用您开始使用的非管道版本。 Good luck!祝你好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.