TypeScript:将数组传递给变量而不是直接传递给函数时出错

时间:2020-05-14 00:35:34

标签: typescript types

以下函数workOnFunctions接收一个对象和该对象的键数组,其中所有键都映射到一个函数:

const myObj = {
    a: () => 1,
    b: "test",
    c: 2,
    d: (a : number) => a*2
}

function workOnFunctions <K extends PropertyKey>(o: Record<K, Function>, names: K[]) {
    names.forEach(name => {
        const f =  o[name]; // do something with function f
    })
}

当我这样做时,我注意到它可以正常工作:

workOnFunctions(myObj, ["a", "d"]); // works

但是当将数组存储在变量中然后将该变量传递给函数时,出现错误

Argument of type '{ a: () => number; b: string; c: number; d: (a: number) => number; }' is not assignable to parameter of type 'Record<string, Function>'.
  Property 'b' is incompatible with index signature.
    Type 'string' is not assignable to type 'Function'.

代码:

const names = ["a", "d"];
workOnFunctions(myObj, names);

为什么会这样?似乎编译器无法正确推断names的类型。当我直接传递数组时,它可以。我也尝试过:

const names = ["a", "d"] as const;
workOnFunctions(myObj, names);

这也不起作用。

我的最终目标是编写一个带有一个对象的函数和一个指向该对象内函数的键数组。

编辑:找到了部分解决方案,但我不明白为什么

看起来像这样:

type KeysMatching<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T]
const names : Array<KeysMatching<typeof myObj, Function>> = ["a", "d"];
workOnFunctions(myObj, names);

我从这里得到KeysMatchingTypeScript: Accept all Object keys that map to a specific type

但是,当我直接传递数组时,为什么编译器可以自行推断这种复杂类型呢?使用单独的数组时,是否还有技巧自动推断类型?

1 个答案:

答案 0 :(得分:0)

您的错误不是由于names数组,而是由于您的myObject, “ b”和“ c”属性不会返回函数,而这正是您在workOnFunctions函数o: Record<K, Function>中定义的。

如果您用正确的类型更改myObj,它将起作用

// adding the type :Record<PropertyKey, Function> is optional here, and will work without having to defined the type.
myObj: Record<PropertyKey, Function> = {
    a: () => 1,
    b: () => "test",
    c: () => 2,
    d: (a : number) => a*2
}