作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在努力改进 Rosie 的定义,它目前非常依赖 any
并且在安全方面没有提供太多。我现在有点卡住了,需要一些建议。
我正在尝试编写一个表达以下内容的签名:
// this is invalid, but something like this is the goal
interface IFactory<T = any> {
attr<K extends keyof T, D extends keyof T>(name: K, dependencies: D[], generatorFunction: (value1?: D[0], value2?: D[1], value3?: D[2]), value4?: D[3] => T[K]): IFactory<T>;
}
第二个参数给出了一个键数组。这些值以提供的相同顺序作为参数传递给函数。我想避免不必要的类型转换,所以我们应该得到这个:
Factory.define<Person>('Person').attr('fullName', ['firstName', 'lastName', 'age'], (firstName, lastName, age) => {
// it knows that firstName is a string, lastName is a string, age is a number
if (age > 10) {
// this will error
return age;
}
return `${firstName} ${lastName};
});
我能得到的最接近的是:
attr<K extends keyof T, D extends keyof T>(name: K, dependencies: D[], generatorFunction: (value1: T[D], value2: T[D], value3: T[D], value4: T[D]) => T[K]): IFactory<T>;
这将键入最多 4 个依赖值,但调用它需要显式转换并且它不会以正确的顺序设置类型:
// it knows that each of the three arguments are string | number
existingDefinition.attr('fullName', ['firstName', 'lastName', 'age'], (firstName: string, lastName: string, age: number) => `${firstName} ${lastName}`);
这使我可以在不破坏依赖项的情况下更改依赖项的顺序,这不好。如果我提供的参数多于依赖值,它也不会给出错误。我想找到一种方法来表达“generatorFunction
对 dependencies
中的每个元素都有一个参数,类型为 T[DependencyName]
”。
我希望这是有道理的。感谢任何人可以提供的任何帮助。
最佳答案
您需要为每个元数(签名)进行重载。例如,看看如何 Reselect做事
/* one selector */
export function createSelector<S, R1, T>(
selector: Selector<S, R1>,
combiner: (res: R1) => T,
): OutputSelector<S, T, (res: R1) => T>;
export function createSelector<S, P, R1, T>(
selector: ParametricSelector<S, P, R1>,
combiner: (res: R1) => T,
): OutputParametricSelector<S, P, T, (res: R1) => T>;
/* two selectors */
export function createSelector<S, R1, R2, T>(
selector1: Selector<S, R1>,
selector2: Selector<S, R2>,
combiner: (res1: R1, res2: R2) => T,
): OutputSelector<S, T, (res1: R1, res2: R2) => T>;
export function createSelector<S, P, R1, R2, T>(
selector1: ParametricSelector<S, P, R1>,
selector2: ParametricSelector<S, P, R2>,
combiner: (res1: R1, res2: R2) => T,
): OutputParametricSelector<S, P, T, (res1: R1, res2: R2) => T>;
/* three selectors */
export function createSelector<S, R1, R2, R3, T>(
selector1: Selector<S, R1>,
selector2: Selector<S, R2>,
selector3: Selector<S, R3>,
combiner: (res1: R1, res2: R2, res3: R3) => T,
): OutputSelector<S, T, (res1: R1, res2: R2, res3: R3) => T>;
export function createSelector<S, P, R1, R2, R3, T>(
selector1: ParametricSelector<S, P, R1>,
selector2: ParametricSelector<S, P, R2>,
selector3: ParametricSelector<S, P, R3>,
combiner: (res1: R1, res2: R2, res3: R3) => T,
): OutputParametricSelector<S, P, T, (res1: R1, res2: R2, res3: R3) => T>;
// etc...
对每个参数进行重载,直到达到合理的数量(您期望多少?4?8?),然后仅使用非限制性泛型并让用户输入。如果您的参数超过 8 个,应该打字不方便。
关于TypeScript 泛型和函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46496735/
我是一名优秀的程序员,十分优秀!