javascript - Flowtype/Typescript 通用获取属性

标签 javascript typescript types flowtype

有没有什么方法可以在流程或 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

在哪里getobj 的通用函数任何类型的。我们能否以流程检查是否 obj 的方式注释代码?有prop

主要用例是为深层属性编写一个通用的 get 函数。与 _.get 具有相似功能的东西.我正在努力避免这种情况:

if (a && a.b && a.b.c && a.b.c.d === 'blah') { ... }

编辑:

如@vkurchatkin 所述,我们可以使用 $Keys .但我只能让它与 1 级深的 getter 函数一起使用。我们如何键入以下函数:

get<T: {}>(obj: T, prop1: $Keys<T>, prop2: /* ! */): /* ! */ { ... }

编辑 2:

到目前为止,我已经写了以下内容:

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

它看起来像在 type Get<T, U> = (obj: T, a: $Keys<T>) => U 中, U不是 obj[a] 值的类型.

最佳答案

你可以用 Flow 做到这一点:

function get<T: {}>(obj: T, prop: $Keys<T>) {
    return obj[prop];
}

不幸的是,返回的类型被推断为any。 Flow 目前有 $PropertyType 正在开发中,所以我相信这在未来应该是可能的(它还没有按预期工作):

function get<T: {}, P: $Keys<T>>(obj: T, prop: P): $PropertyType<T, P> {
    return obj[prop];
}

使用这种类型,您将能够深入两个层次:

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];
}

或者使某些东西可组合。

关于javascript - Flowtype/Typescript 通用获取属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38926674/

相关文章:

javascript - 在php中以编程方式生成数组名称

javascript - Socket.io - 无法停止将所有数据传递给所有客户端

typescript - NestJS 测试 Controller 中间件

java - 我们可以使用类型名称作为变量吗

javascript - CSS 应该包含在 NPM 组件库中还是手动加载?

JavaScript:在 Android 上阻止文本输入时的退格键

typescript - 将被减数与差的交集分配给减数与被减数的交集

typescript - `use` 指令的返回类型是什么?

c++ - 为什么 int 不能用作返回类型的左值,而用户定义的类可以?

haskell - 约束种类中的相等约束