-1

I am trying to constraint key so it can only reference keys of TItem that are number or Date.

public static indexOfMin<TItem extends object | number | Date>(array: Array<TItem>, key?: keyof TItem): number {
    let min: number = Number.MIN_SAFE_INTEGER;
    let index: number = -1;
    const length = array.length;
    for (let i = 0; i < length; i++) {
        const value = Number(isNullOrUndefined(key) ? array[i] : array[i][key]);
            if (value < min) {
                min = value;
                index = i;
            }
     }
    return index;
    }

interface IPerson {
    name: string;
    age: number;
    dob: Date;
}

indexOfMin(new Array<IPerson>(), 'name'); // error as name is string.
indexOfMin(new Array<IPerson>(), 'age'); // ok are age is number.
indexOfMin(new Array<IPerson>(), 'dob'); // ok are age is Date.
Rob
  • 14,746
  • 28
  • 47
  • 65

1 Answers1

0

You can do it by adding also conditional types. It looks a bit complicated but does the job. There is a similar sample in the TypeScript documentation chapter about Distributive conditional types.

Here is a sample how you can define such a type that selects only property names that are number and Date:

type NumberOrDatePropertyNames<T> = { [K in keyof T]: T[K] extends number | Date ? K : never }[keyof T];

The K is the key of the type T. Then you limit the T[K] which is the type of the actual property with the key K with a conditional type that returns the key K if the property is number or date else it matches to never which means it is ignored.

Then your function parameter can be changed to use this type and the keys will be limited only to number and Date properties.

public static indexOfMin<TItem extends object | number | Date>(array: Array<TItem>, key?: NumberOrDatePropertyName<TItem>): number {
    let min: number = Number.MIN_SAFE_INTEGER;
    let index: number = -1;
    const length = array.length;
    for (let i = 0; i < length; i++) {
        const value = Number(isNullOrUndefined(key) ? array[i] : array[i][key]);
            if (value < min) {
                min = value;
                index = i;
            }
     }
    return index;
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Aleš Doganoc
  • 11,568
  • 24
  • 40