将条件类型和映射类型与数组归约方法一起使用

时间:2018-08-11 08:41:51

标签: typescript

我想通过 <div class=""> <button style="background-color:transparent" id="left-arrow" class="glyphicon glyphicon-menu-left slider"></button> </div> 实现一个通用的sum方法,该方法总结一个实体的特定数字属性。

Array.prototype.reduce应该接受两个参数:

  • 通用实体类型E
  • 其属性之一限制为sum返回值

我试图在此处使用conditional and mapped types

类型定义:

number

数据:

type MeasureableEntityPropNames<E> = 
   { [K in keyof E]: E[K] extends number ? K : never }[keyof E];
type MeasurableEntity<E> = Pick<E, MeasureableEntityPropNames<E>>;

type MyEntity = {
    p1: number,
    p2: string,
    p3: Date,
    p4: number
};

求和方法和调用:

let entities: MyEntity[] = [
    { p1: 1, p2: "str", p3: new Date(), p4: 3 },
    { p1: 2, p2: "str2", p3: new Date(), p4: 1 }
]

错误:

  

运算符'+'不能应用于类型'number'和'Pick [{[keyof中的K   E]:E [K]扩展数? K:从不; } [E键]]。

类型定义是否存在问题,或者打字稿不能推断出const sum = <E>(elements: MeasurableEntity<E>[], prop: keyof MeasurableEntity<E>) => elements.reduce((acc: number, cur: MeasurableEntity<E>) => { return acc + cur[prop]; // ERROR }, 0); sum<MyEntity>(entities, "p1"); 的类型为cur[prop]?这里要更改什么?

问候

(打字稿3.0.1)

1 个答案:

答案 0 :(得分:2)

虽然您限制键的方法对调用者有效,但是在Typescript函数内部将无法确定键指定的字段将始终是数字,因为在这种情况下不会评估条件类型直到知道类型参数为止。

通过使用key作为泛型类型参数,并指定传入的数组必须为记录,而作为type参数传入的键必须为数字,我们可以轻松解决此问题。自然地,我们可以指定一个具有更多键作为参数的实体,但是作为第二个参数传入的键将必须指向数字字段

const sum = <K extends string>(elements: Record<K, number>[], prop: K) =>
    elements.reduce((acc: number, cur) => {
        return acc + cur[prop];      
    }, 0);

type MyEntity = {
    p1: number
    p2: string,
    p3: Date,
    p4: number
};
let entities: MyEntity[] = [
    { p1: 1, p2: "str", p3: new Date(), p4: 3 },
    { p1: 2, p2: "str2", p3: new Date(), p4: 1 }
]
sum(entities, "p1");
sum(entities, "p2"); //Error