Ограничить ключ, поэтому он может ссылаться только на ключи TItem, которые являются числом или датой - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь ограничить ключ, чтобы он мог ссылаться только на ключи TItem, которые являются числом или датой.

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.

1 Ответ

0 голосов
/ 10 июля 2019

Вы можете сделать это, добавив также условные типы. Это выглядит немного сложным, но делает работу. В главе документации по TypeScript есть похожий пример о Распределительные условные типы .

Вот пример того, как вы можете определить такой тип, который выбирает только имена свойств, которые являются числом и датой:

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

K - это ключ типа T. Затем вы ограничиваете T [K], который является типом фактического свойства, ключом K условным типом, который возвращает ключ K, если свойство является числом или датой, иначе оно соответствует никогда, что означает, что оно игнорируется.

Тогда ваш функциональный параметр может быть изменен для использования этого типа, а ключи будут ограничены только свойствами number и Date.

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