首页 > 解决方案 > 具有属性名和值参数的通用函数

问题描述

是否可以编写一个带有 2 个参数的通用函数,其中第一个参数是属性名,第二个是属性值?

这个(不工作的)打字稿显示了我的意图:

declare function add<F extends Record<string, unknown>>(name: keyof F, value: T[path]): void;
add<{a: number; b: boolean}>('a', true); // Should be number

所以当我用错误的值参数调用 add 时,我得到类型错误。

编辑 我意识到我真正想要的是输入一个带有重载签名的函数。

declare function add<F extends any>(obj: F, prop: keyof F, value: F[typeof prop]): void;
add({a: 1, b: false}, 'b', 42); // should give compiler error

这里它是值参数,编译器推断为number | boolean,所以它满足任何一个。但是显然,没有办法根据第一个参数来反映类型。

标签: typescripttypescript-generics

解决方案


你可以咖喱你的功能:

const add = <
    Key extends PropertyKey,
    Value,
    Obj extends Record<Key, Value>,
    Name extends keyof Obj
>(obj: Obj, name: Name, value: Obj[Name]):
    Obj[Name] => null as any

const result = add({ a: 42, b: true }, 'a', 42)

add({ a: 1, b: false }, 'b', 42); // error


函数的第一部分:

Key- 推断对象键

Value- 推断对象值

Obj- 推断整个对象

Name- 推断name论点

Obj[Name]- 我不确定value限制。

操场

在这里,在我的博客中,您可以找到有关函数参数推断的更多信息

更新

我认为你需要推断obj.

在这里,您有一个替代版本:

type Obj = { a: number; b: boolean }

const add = <
    Name extends keyof Obj
>(name: Name, value: Obj[Name]):
    Obj[Name] => null as any

const result = add('a', 42)

add('b', 42); // error

操场


推荐阅读