Общие типы TypeScript предоставляют мощный способ написания многократно используемого и гибкого кода. Однако в некоторых случаях может потребоваться запретить использование литеральных типов в качестве аргументов типа в универсальных типах. В этой статье рассматриваются несколько способов добиться этого, а также приводятся примеры кода.
Метод 1: использование ограничений типов с типами объединения
Один из способов предотвратить использование литеральных типов — использовать ограничения типов с типами объединения. Определив тип объединения, исключающий литеральные типы, которые вы хотите предотвратить, вы можете обеспечить соблюдение ограничения в универсальном типе. Вот пример:
type NonLiteralType<T> = T extends 'literal' ? never : T;
function processValue<T extends NonLiteralType<string>>(value: T): void {
// Process the value
}
processValue('literal'); // Error: Argument of type 'literal' is not assignable to parameter of type 'NonLiteralType<string>'
В этом примере тип NonLiteralTypeисключает литерал типа 'literal'. Затем функция processValueиспользует это ограничение типа, чтобы предотвратить использование литерального типа в качестве аргумента.
Метод 2: использование защиты типов
Другой подход заключается в использовании защиты типов для предотвращения использования литеральных типов. Создав настраиваемую защиту типа, которая проверяет литеральные типы, вы можете использовать ее для условного применения ограничения. Вот пример:
type NonLiteralType<T> = T extends string ? string : never;
function processValue<T extends NonLiteralType<T>>(value: T): void {
// Process the value
}
function isLiteral(value: string): value is 'literal' {
return value === 'literal';
}
const value: string = 'literal';
if (!isLiteral(value)) {
processValue(value); // OK
}
const literalValue: 'literal' = 'literal';
if (!isLiteral(literalValue)) {
processValue(literalValue); // Error: Argument of type '"literal"' is not assignable to parameter of type 'NonLiteralType<"literal">'
}
В этом примере тип NonLiteralTypeиспользует условный тип для исключения литеральных типов. Функция processValueзатем защищена защитой типа isLiteral, которая гарантирует, что в качестве аргументов передаются только нелитеральные значения.
Метод 3: использование индексированных типов доступа
Индексированные типы доступа также можно использовать для предотвращения использования литеральных типов в универсальных типах. Создав индексированный тип доступа, который сопоставляет литеральные типы с другим типом, вы можете эффективно исключить их. Вот пример:
type NonLiteralType<T> = T extends string ? string : never;
function processValue<T extends NonLiteralType<T>>(value: T): void {
// Process the value
}
type NonLiteralMap = {
[K in keyof typeof values]: NonLiteralType<typeof values[K]>;
};
const values = {
literal: 'literal',
nonLiteral: 'nonLiteral',
};
function getValue<K extends keyof NonLiteralMap>(key: K): NonLiteralMap[K] {
return values[key];
}
const value = getValue('nonLiteral');
processValue(value); // OK
const literalValue = getValue('literal');
processValue(literalValue); // Error: Argument of type '"literal"' is not assignable to parameter of type 'NonLiteralType<string>'
В этом примере тип NonLiteralTypeиспользуется для исключения литеральных типов. Тип NonLiteralMapсопоставляет ключи объекта valuesс соответствующими нелитеральными типами. Функция getValueизвлекает значения из объекта values, гарантируя, что возвращаются только нелитеральные значения.
Предотвратить литеральные типы в универсальных типах TypeScript можно с помощью различных методов, таких как ограничения типов с типами объединения, средства защиты типов и индексированные типы доступа. Каждый метод обеспечивает свой подход к обеспечению соблюдения ограничения. Выбрав наиболее подходящий метод для вашего случая использования, вы можете обеспечить безопасность типов и повысить гибкость своего кода.