0

Опциональные параметры на основе условных типов

30

Проблема с обязательными и необязательными параметрами функции в TypeScript

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

const foo = <T extends string | number>(
    first: T,
    second: T extends string ? boolean : undefined
) => undefined;

foo('foo', true); // все работает, как задумано
foo(2, true); // ошибка, как задумано
foo(2, undefined); // все работает, как задумано
foo(2); // ошибка компилятора! Я хотел бы, чтобы это было допустимо

Как сделать так, чтобы вызов foo(2) не вызывал ошибку компилятора, при этом сохранив остальные проверки? Спасибо!

1 ответ(ов)

0

Чтобы создать условный тип для аргументов функции foo, вы правильно подошли к задаче. Ваше решение выглядит аккуратно и логично. Давайте рассмотрим, как оно работает.

Мы определяем тип FooArgs, который зависит от того, является ли тип T строкой или числом. Если T — это строка, тогда функция ожидает массив из двух элементов: первый элемент — это T, а второй — булевый тип. Если T — это число, тогда первый элемент также будет T, а второй элемент будет необязательным и равным undefined.

Вот ваш код с объяснениями:

// Определяем условный тип FooArgs
type FooArgs<T extends string | number> = 
    T extends string ?                // Если T — строка
    [first: T, second: boolean] :     // Тогда ожидание [T, boolean]
    [first: T, second?: undefined];   // Если T — число, то [T, undefined?]

const foo = <T extends string | number>(...args: FooArgs<T>) => {
    const [first, second] = args;
    // Здесь вы можете выполнять дополнительные действия с аргументами
};

// Примеры использования
foo('foo', true); // ok, как и планировалось
foo(2, true);     // ошибка, как и планировалось, так как для числа не ожидается второй аргумент
foo(2, undefined); // ok, как и планировалось, второй аргумент необязательный
foo(2);           // ok, как и планировалось, только первый аргумент
foo('foo');      // ошибка, как и планировалось, строка требует второй аргумент

Если вы выполняете все проверки корректно и ожидаете именно такое поведение, то ваш подход верен. Так что вы правильно упростили изначальные ответы, сделав их более понятными и структурированными.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь