Вызов функции хотя бы с одним аргументом, какой тип?

Есть функция

type Time = {
  days?: number
  hours?: number
  minutes?: number
  seconds?: number
}

const timeToMilliseconds = ({ days, hours, minutes, seconds }: Time) => {
  if (days) return days * 24 * 60 * 60 * 1000;
  if (hours) return hours * 60 * 60 * 1000;
  if (minutes) return minutes * 60 * 1000;
  if (seconds) return seconds * 1000;
};

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

Вопрос в том как создать тип который будет указывать на то что в функция должна быть вызвана хотя бы с одним аргументом, для того что бы исключить возврат undefined ?


Ответы (1 шт):

Автор решения: qwabra

namespace A

для того что бы исключить возврат undefined

namespace A {
    const [days, hours, minutes, seconds] = [1, 2, 3, 4]
    type Time = {
        days?: number
        hours?: number
        minutes?: number
        seconds?: number
    }

    namespace T1 {
        const timeToMilliseconds = ({ days, hours, minutes, seconds }: Time) => {
            if (days) return days * 24 * 60 * 60 * 1000;
            if (hours) return hours * 60 * 60 * 1000;
            if (minutes) return minutes * 60 * 1000;
            if (seconds) return seconds * 1000;
            return 0
        }
        //@ts-expect-error 
        timeToMilliseconds({})// плохо - нет ошибки
        timeToMilliseconds({ days })// ok
        timeToMilliseconds({ hours })// ok
        timeToMilliseconds({ minutes })// ok
        timeToMilliseconds({ seconds })// ok
        //@ts-expect-error
        timeToMilliseconds({ days, hours, minutes, seconds })// нет ошибки
    }

    namespace T2 {
        const timeToMilliseconds = ({ days, hours, minutes, seconds }: Time) => {
            if (days) return days * 24 * 60 * 60 * 1000;
            if (hours) return hours * 60 * 60 * 1000;
            if (minutes) return minutes * 60 * 1000;
            if (seconds) return seconds * 1000;
            else throw new TypeError('days, hours, minutes and seconds is not set')
        }
        //@ts-expect-error
        timeToMilliseconds({})// плохо - нет ошибки
        timeToMilliseconds({ days })// ok
        timeToMilliseconds({ hours })// ok
        timeToMilliseconds({ minutes })// ok
        timeToMilliseconds({ seconds })// ok
        //@ts-expect-error
        timeToMilliseconds({ days, hours, minutes, seconds })// нет ошибки
    }
}

namespace B

функция должна быть вызвана хотя бы с одним аргументом

namespace B {
    const [days, hours, minutes, seconds] = [1, 2, 3, 4]

    namespace T1 {
        type Time_2 = { days: number } | { hours: number } | { minutes: number } | { seconds: number }
        const timeToMilliseconds = (time: Time_2) => {
            if ('days' in time) return time.days * 24 * 60 * 60 * 1000;
            if ('hours' in time) return time.hours * 60 * 60 * 1000;
            if ('minutes' in time) return time.minutes * 60 * 1000;
            if ('seconds' in time) return time.seconds * 1000;
            else throw new TypeError('days, hours, minutes and seconds is not set')
        }
        //@ts-expect-error
        timeToMilliseconds({})// ok - TS сообщает об ошибке
        timeToMilliseconds({ days })// ok
        timeToMilliseconds({ hours })// ok
        timeToMilliseconds({ minutes })// ok
        timeToMilliseconds({ seconds })// ok
        //@ts-expect-error
        timeToMilliseconds({ days, hours, minutes, seconds })// нет ошибки
    }

    namespace T2 {
        // interface $timeToMilliseconds {
        type $timeToMilliseconds = {
            (time: { days: number }): number;
            (time: { hours: number }): number;
            (time: { minutes: number }): number;
            (time: { seconds: number }): number;
        }
        const timeToMilliseconds: $timeToMilliseconds = (time: Record<any, any>) => {
            if ('days' in time) return time.days * 24 * 60 * 60 * 1000;
            if ('hours' in time) return time.hours * 60 * 60 * 1000;
            if ('minutes' in time) return time.minutes * 60 * 1000;
            if ('seconds' in time) return time.seconds * 1000;
            else throw new TypeError('days, hours, minutes and seconds is not set')
        }
        //@ts-expect-error
        timeToMilliseconds({})// ok - TS сообщает об ошибке
        timeToMilliseconds({ days })// ok
        timeToMilliseconds({ hours })// ok
        timeToMilliseconds({ minutes })// ok
        timeToMilliseconds({ seconds })// ok
        //@ts-expect-error
        timeToMilliseconds({ days, hours, minutes, seconds })// TS сообщает об ошибке
    }
}
→ Ссылка