简体   繁体   English

TypeScript 泛型和函数参数

[英]TypeScript generics and function arguments

I'm working on improving the defs for Rosie , which currently rely a lot on any and don't offer much in the way of safety.我正在努力改进Rosie的 defs,它目前非常依赖any并且在安全方面没有提供太多。 I'm a little stuck at the moment and could use some advice.我现在有点卡住了,可以使用一些建议。

I'm trying to write a signature that expresses the following:我正在尝试编写一个表达以下内容的签名:

// 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>;
}

An array of keys is given in the second argument.第二个参数中给出了一个键数组。 The values of those are passed in as arguments to the function in the same order provided.这些值以提供的相同顺序作为参数传递给函数。 I want to avoid unnecessary type casts, so we should get this:我想避免不必要的类型转换,所以我们应该得到这个:

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};     
});

The closest I can get is this:我能得到的最接近的是这个:

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>;

That will type up to 4 dependent values, but calling it requires explicit casts and it doesn't set types in the correct order:这将输入最多 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}`);

This makes it possible for me to change the order of dependencies without it breaking, which is no good.这使我可以在不中断的情况下更改依赖关系的顺序,这是不好的。 It also doesn't give an error if I provide more arguments than dependent values.如果我提供的参数多于依赖值,它也不会出错。 I'd like to find a way of expressing " generatorFunction has one argument for each element in dependencies , of type T[DependencyName] ."我想找到一种表达方式“ generatorFunctiondependencies每个元素都有一个参数,类型为T[DependencyName] 。”

I hope this makes sense.我希望这是有道理的。 Appreciate any help anyone can offer.感谢任何人可以提供的任何帮助。

You will need to make overloads for each arity (signature).您将需要为每个 arity(签名)进行重载。 For example, take a look at how Reselect does things比如看一下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...

Make overloads for each number of arguments until a reasonable number (how many are you expecting? 4? 8?) and past that just use a non-constricted generic and let the user input it.对每个参数进行重载,直到一个合理的数字(你期望有多少?4?8?),然后只使用非限制泛型并让用户输入它。 If you have more than 8 parameters, it should hurt you to type.如果你有超过8个参数,它应该伤害你打字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM