[英]Flowtype/Typescript general purpose get property
Is there any way to properly type check the following code in either flow or typescript?: 有什么方法可以在流或打字稿中正确键入以下代码?
type A = {
x: string
}
type B = {
y: string
}
function get(obj, prop) {
return obj[prop];
}
const a: A = { x: 'x' }
const b: B = { y: 'y' }
get(a, 'x') // should type check
get(b, 'y') // should type check
get(a, 'y') // should NOT type check
get(b, 'x') // should NOT type check
Where get
is a general purpose function for obj
of any type. 其中, get
是任何类型的obj
的通用函数。 Can we annotate the code in a way that flow will check if obj
has prop
? 我们是否可以通过流程将检查obj
是否具有prop
的方式注释代码?
The main use case is writing a general purpose get function for deep properties. 主要用例是为深层属性编写通用的get函数。 Something with similar functionality as _.get
. 具有与_.get
类似的功能。 I'm trying to avoid this situation: 我正在努力避免这种情况:
if (a && a.b && a.b.c && a.b.c.d === 'blah') { ... }
As mentioned by @vkurchatkin, we can use $Keys
. 如@vkurchatkin所述,我们可以使用$Keys
。 But I can only get that to work with a getter function that is 1 level deep. 但是我只能将其与深度为1级的getter函数一起使用。 How do we type the following function: 我们如何键入以下函数:
get<T: {}>(obj: T, prop1: $Keys<T>, prop2: /* ! */): /* ! */ { ... }
I have written the following so far: 到目前为止,我已经写了以下内容:
type A = {
x: B
}
type B = {
y: string
}
type GetDeep<T: {}, U, V> = Helper<T, U, V, Get<T, U>, Get<U, V>>
type Helper<T, U, V, W, X> = (obj: T, a: $Keys<T>, b: $Keys<U>) => V
type Get<T, U> = (obj: T, a: $Keys<T>) => U;
// NOTE: here if I replace GetDeep<*, B, *> with GetDeep<*, *, *>
// then it wrongly type checks everything
const getDeep: GetDeep<*, B, *> = (obj, a, b) => {
return obj[a][b];
}
var va: A = {
x: {y: 'abc'}
}
getDeep(va, 'x', 'y'); // ok
getDeep(va, 'x', 'z'); // error
It looks like in type Get<T, U> = (obj: T, a: $Keys<T>) => U
, U
is not the type of the value of obj[a]
. 看起来像type Get<T, U> = (obj: T, a: $Keys<T>) => U
, U
不是obj[a]
值的类型。
You can do it with Flow: 您可以使用Flow来做到这一点:
function get<T: {}>(obj: T, prop: $Keys<T>) {
return obj[prop];
}
Unfortunately, returned type is inferred as any
. 不幸的是,返回的类型被推断为any
。 Flow has currently has $PropertyType
in the works, so I believe this should be possible in the future (it doesn't work as expected yet): Flow目前正在开发$PropertyType
,因此我相信将来应该可以(它无法按预期运行):
function get<T: {}, P: $Keys<T>>(obj: T, prop: P): $PropertyType<T, P> {
return obj[prop];
}
With this type you will be able to go two levels deep: 使用这种类型,您将可以深入两个层次:
function getDeep<
T: {},
P: $Keys<T>,
R: $PropertyType<T, P>,
P2: $Keys<R>
>(obj: T, a: P, b: P2): $PropertyType<R, P2> {
return obj[a][b];
}
Or make something composable. 或使某些东西变得可组合。
Where get is a general purpose function for obj of any type. 其中,get是任何类型的obj的通用函数。 Can we annotate the code in a way that flow will check if obj has prop 我们是否可以通过以下方式对代码进行注释,即流程将检查obj是否具有prop
You can't do that with TypeScript. 您不能使用TypeScript做到这一点。
Something with similar functionality as _.get 具有与_.get类似的功能
It would be much easier if safe navigation operator becomes available : https://github.com/Microsoft/TypeScript/issues/16 如果可以使用安全的导航操作符,将会容易得多: https : //github.com/Microsoft/TypeScript/issues/16
However the JavaScript committee needs to get on it and as far as I can see its sadly not being championed by anyone. 但是JavaScript委员会需要继续努力,据我所知,可悲的是它没有受到任何人的拥护。
Till then I've also done a && ab
etc. 直到那时,我还完成a && ab
等。
A slow function I've used sometimes when cleaning up other peoples code: 我在清理其他人的代码时有时会使用的慢速功能:
export function safe<T>(action: () => T): T | undefined {
try {
return action();
}
catch (ex) {
return undefined;
}
}
// Usage
let c = safe(()=>a.b.c);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.