【问题标题】:Strong types for a function getting a value from object从对象获取值的函数的强类型
【发布时间】:2020-10-15 17:06:33
【问题描述】:

我有一个从对象中按键获取值的功能,它允许我在使用它时查看记录中可能键的建议。该函数从它的参数推断类型。

function get, K1 extends keyof T>(
    记录:T |不明确的,
    键1:K1
): T[K1] |不明确的

const foo = { bar: 1, baz: 2 }
get(foo, 'bar') // 1, get

是否可以将其转换为无点样式,保留强类型并且不丢失建议?与此类似。

function get<T extends Record<string, any>, K1 extends keyof T>(key1: K1):
    (record: T | undefined) => T[K1] | undefined

const foo = { bar: 1, baz: 2 }
get('bar')(foo) // 1, get<{ a: number, b: number }>

显然这不起作用。我尝试了 pointfree 函数的多种变体,但我无法让它工作。 我查看了函数propramda 实现,它可以无点工作,但它不提供建议,因为它允许任何字符串作为键。

type prop = <P extends string>(key: P) => <T>(obj: Record<P, T>) => T

const foo = { bar: 1, baz: 2 }
prop('bar')(foo) // 1, prop: <"bar">(key: "bar") => <T>(obj: Record<"bar", T>) => T

编辑:

为了清楚起见,我知道如果不先指定记录,我将无法获得建议。

prop('...') // no suggestions here
prop('...')(foo) // now I want suggestions

【问题讨论】:

  • 那只是柯里化,与pointfree无关。
  • 如果你先指定key你不能真正得到建议,你可以得到prop(foo)('bar')给你建议
  • 是的,我想以积分方式使用它,但弄糊涂了。

标签: typescript typescript-typings


【解决方案1】:

我高度怀疑这是不可能的,因为依赖关系的顺序是颠倒的。如果要先提供对象,那将不是问题。

现在您必须通过泛型手动指定对象的类型,例如:

const get = <T extends Record<K1, any>, K1 extends keyof T>(key1: K1) =>
    (record: T) => record[key1];

const foo = { bar: 1, baz: 2 }
get<typeof foo, keyof typeof foo>('bar')(foo)

【讨论】:

  • 我不确定我是否理解我想要获得建议的确切程度。即使按照我在编辑中指定的方法也不可能?
  • @PetrD.Svoboda:是的,我认为这是不可能的。
  • @H.B.,如果返回类型本身是泛型的,则有可能。
  • 好的。似乎我错过了这个问题。你是对的。
【解决方案2】:

Here is it(甚至可以使用in typescript 3.3,没有要检查的旧版本):

function get<K extends keyof any>(key: K): <T extends { [key in K]: any }>(x: T) => T[K] {
    return x => x[key]
}

const foo = { bar: 1, baz: "2" }

const x = get('bar')(foo) // number
const y = get('baz')(foo) // string

const z = get('oops')(foo) // Argument of type '{ bar: number; baz: string; }' is not assignable to parameter of type '{ oops: any; }'

哎呀。错过了关于自动建议的要点。它们不会以这种方式工作,因为在大多数情况下应该从左到右工作,这个也不例外。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2020-01-29
    • 2018-10-16
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多