打字稿中类型的通用映射
让我们想象一下类型T:
lets imagine type T:
type T = {
prop1: (s: S) => T1,
prop2: (s: S) => T2,
prop3: (s: S) => T3,
}
现在让我们想象一下类型W
and now lets imagine type W
type W = (s: S) => {
prop1: T1,
prop2: T2,
prop3: T3,
}
易于编写将T映射到W的函数,
its easy to write a function that maps T to W by hand,
是否可以在打字稿中编写其通用类型的sefe版本?
is it possible to write generic type sefe version of it in typescript?
function x(t: T): W {
return funtion(s: S) {
prop1: t.prop1(s),
prop2: t.prop2(s)
prop3: t.prop3(s)
}
}
缺少哪种功能语言来实现此目的,例如高阶通用类型?
what kind of feature language is missing to facilitate this, something like higher order generic types?
您确实可以在TypeScript中编写此版本的通用版本:
You can indeed write a generic version of this in TypeScript:
function x<S, V>(t: {[K in keyof V]: (s: S) => V[K]}): (s: S) => V {
return function(s: S): V {
const ret = {} as V;
Object.keys(t).forEach((k: keyof V) => {
ret[k] = t[k](s);
})
return ret;
}
}
const xSpecific: (t: T) => W = x; // okay
请注意,V
是W
函数的返回类型. (因此W
本质上与(s: S) => V
相同.)x
的输入是
Note that V
is the return type of your W
function. (So W
is essentially the same as (s: S) => V
.) And the input to x
is a mapped type corresponding to T
: it has the same keys as V
, but its values are functions from S
to the corresponding properties of V
.
因为TypeScript支持提议的扩展typeof
"功能的东西通常来自T
的W
. (这可能是您所暗示的缺少的语言功能.)
You can get away with having the function input being a mapped type and the output being an unmapped one because TypeScript supports inference from mapped types. Otherwise you'd need something like the proposed "extended typeof
" feature to derive W
from T
generically. (This might be the missing language feature to which you're alluding.)
对于实现,我遍历t
的键并将每个功能t[k]
应用于输入s
.
As for the implementation, I'm looping over the keys of t
and applying each function t[k]
to the input s
.
和xSpecific
与x
相同,只限于您发布的特定T
和W
类型.进行编译是因为TypeScript识别出通用x
是兼容的.
And xSpecific
is the same as x
narrowed to the particular T
and W
types you posted. This compiles because TypeScript recognizes that the generic x
is compatible.
现在进行警告和精美印刷.不幸的是,编译器无法直接从x
可靠地推断S
的类型.如果仅使用T
输入调用通用x()
,则会得到以下信息:
Now for the caveats and fine print. Unfortunately, the compiler isn't able to reliably infer the type of S
from x
directly. If you just call the generic x()
with a T
input, you get this:
declare const t: T;
const w = x(t); // (s: {}) => { prop1: T1; prop2: T2; prop3: T3; }
w
并不完全是W
...它接受任何输入,而不仅仅是S
.如果您确实需要缩小输入类型,则必须自己手动指定通用参数来完成此操作:
The w
is not exactly a W
... it accepts any input, not just an S
. If you really need to narrow the type of input, you'll have to do it yourself by manually specifying the generic parameters:
const w = x<S, {prop1: T1, prop2: T2, prop3: T3}>(t);
很难看,或者通过断言或注释手动缩小结果w
:
which is ugly, or narrowing the resulting w
manually by assertion or annotation:
const w: W = x(t);
无论如何,希望能有所帮助.祝你好运!
Anyway, hope that helps. Good luck!