【发布时间】:2018-12-18 09:37:10
【问题描述】:
我创建了一个 TypeScript curried 函数,它首先接收属性名称作为字符串,然后接收对象以从中获取该属性的值。 我使用了索引类型来确保每当我尝试访问不存在的属性时都会收到错误:
export interface Dict {
name: string;
age: number;
}
const prop = <T extends Dict, K extends keyof T>(p: K) => (obj: T): T[K] => obj[p];
prop('name')({name: 'John', age: 45}); // John
prop('name2')({name: 'John', age: 45}); // error...
最后一行给出了错误:
error TS2345: Argument of type '"name2"' is not assignable to parameter of type '"name" | "age"'.
这正是我想要的,因为属性 name2 在作为第二个参数给出的对象上不存在。
但是,当我尝试使用 Maybe monad 创建安全版本时,它会给出类似的错误:
const safeProp = <T extends Dict, K extends keyof T>(p: K) => (obj: T): Maybe<{}> => compose2(Maybe.of, prop(p))(obj);
错误出现在compose2函数的第二个参数上:prop(p):
Argument of type 'K' is not assignable to parameter of type '"name" | "age"'.
我不明白,因为我声明了 K extends keyof T,我认为这是正确的,因为它也适用于 prop 函数。
供参考,compose2 函数:
const compose2 = <A, B, C>(f: (b: B) => C, g: (a: A) => B): ((a: A) => C) => a => f(g(a));
以及Maybe monad 的相关部分:
class Maybe<A> {
static of<A>(x: A): Maybe<A> {
return new Maybe(x);
}
...
}
如何正确键入safeProp 函数,为什么我需要将其返回类型指定为Maybe<{}> 而不是Maybe<T[K]>?
【问题讨论】:
标签: typescript functional-programming