我试图为以下功能编写类型
function get(prop) {
return (obj) => obj[prop];
}
我最初尝试使用keyof
,但我无法让它发挥作用。现在我得到了这个:
function get<K extends string>(prop: K) {
return <V, T extends {K: V}>(obj: {K: V}) => obj[prop];
}
但它给出了错误
error TS2536: Type 'K' cannot be used to index type '{ K: V; }'.
因为{K: V}
似乎有一个键K
,所以看起来有点傻。
是否可以使函数类型安全,以便第一个参数必须是一个字符串,并且返回函数的参数必须是具有正确属性的对象?
更新:感谢您的回答。但是,这两种解决方案都存在问题。请考虑以下代码:
function get<K extends string>(prop: K) {
return <V, Obj extends Record<K, V>>(obj: Obj): Obj[K] => obj[prop];
}
const a = get("foo")({ foo: 1 });
a + 12;
最后一行导致错误,因为TypeScript推断出{}
的{{1}}类型。这使得函数使用起来非常麻烦,因为必须强制转换a
。
答案 0 :(得分:2)
它似乎至少适用于夜间构建:
function get<K extends string>(prop: K) {
return <V, Obj extends Record<K, V>>(obj: Obj) => obj[prop];
}
答案 1 :(得分:1)
AlexG的answered确实有效。您也可以在没有Record
的情况下执行此操作。这里的代码说明了两者。 get
使用Record<K, V>
而get2
使用{[x in K]: V}
。
function get<K extends string>(prop: K) {
return <V, Obj extends Record<K, V>>(obj: Obj) => obj[prop];
}
function get2<K extends string>(prop: K) {
return <V, T extends {[x in K]: V}>(obj: T) => obj[prop];
}
const foo = {
"a": 1,
"b": 2,
};
console.log(get("b")(foo));
console.log(get2("b")(foo));
// This line should compile fine in recent development versions and
// presumably will work fine in regular releases from 2.2.0 onwards.
// There's a bug in 2.1.x that causes the type inference to bork and
// cause the compiler to think were adding 1 to a plain object (`{}`).
console.log(get2("b")(foo) + 1);
我想到了上面的内容然后虽然get2
我可能正在复制Record
做的事情和lo and behold,但情况就是这样,因为Record
被定义为这样:
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends string, T> = {
[P in K]: T;
}
您在更新中提到的类型推断问题是TypeScript中的一个错误,该错误已在相对较新版本的TypeScript中修复。 (Alex mentions版本2.2.0-dev.20161221。我尝试过更新的版本,并且还获得了完美的编译。)据推测,它将在版本2.2.0中修复。我不知道任何解决方案会修复2.2.0之前的版本中的编译错误,并且不会有其他负面副作用。