Опциональные параметры на основе условных типов
Проблема с обязательными и необязательными параметрами функции в 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 ответ(ов)
Чтобы создать условный тип для аргументов функции 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'); // ошибка, как и планировалось, строка требует второй аргумент
Если вы выполняете все проверки корректно и ожидаете именно такое поведение, то ваш подход верен. Так что вы правильно упростили изначальные ответы, сделав их более понятными и структурированными.
JSDoc аналог `as const` в TypeScript?
Как в TypeScript типизировать объект с известными и неизвестными ключами?
Разница между "require(x)" и "import x"
@Directive против @Component в Angular
ESLint: 8.0.0 Не удалось загрузить плагин '@typescript-eslint'