← Назад к вопросам

Как обеспечить поддержку шрифтов на старых устройствах?

2.0 Middle🔥 91 комментариев
#HTML и CSS#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ограничение Generic параметров в TypeScript

Ограничение Generic параметров (Generic Constraints) позволяет указать, какие типы могут быть переданы в качестве параметра типа. Это обеспечивает типизацию и предотвращает передачу несовместимых типов.

1. Основной синтаксис - extends

Для ограничения Generic используется ключевое слово extends:

// Ограничение на объект
function printObject<T extends object>(obj: T): void {
  console.log(obj);
}

printObject({ name: 'John' }); // OK
printObject('string');          // Ошибка: string не является object

// Ограничение на конкретный тип
function getId<T extends { id: number }>(item: T): number {
  return item.id;
}

getId({ id: 1, name: 'John' }); // OK
getId({ name: 'John' });        // Ошибка: свойство 'id' отсутствует

2. Ограничение на встроенные типы

// Только строки и числа
function process<T extends string | number>(value: T): T {
  return value;
}

process('hello');   // OK
process(42);        // OK
process(true);      // Ошибка: boolean не в union

// Только массивы
function getLength<T extends any[]>(arr: T): number {
  return arr.length;
}

getLength([1, 2, 3]);        // OK
getLength('string');         // Ошибка: string[] ожидается

// Только функции
function executeFunction<T extends (...args: any[]) => any>(fn: T): any {
  return fn();
}

executeFunction(() => 'test');     // OK
executeFunction('not a function'); // Ошибка

3. Ограничение на класс и его наследников

class Animal {
  name: string = '';
  move() { console.log('Moving'); }
}

class Dog extends Animal {
  bark() { console.log('Woof'); }
}

// Принимает только Animal или его наследников
function createInstance<T extends Animal>(constructor: new () => T): T {
  return new constructor();
}

const dog = createInstance(Dog);      // OK
const animal = createInstance(Animal); // OK

class NotAnimal {}
const notAnimal = createInstance(NotAnimal); // Ошибка

4. Ограничение с keyof

Ограничение Generic параметра на ключи объекта:

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const person = { name: 'John', age: 30 };

getProperty(person, 'name');  // OK, возвращает string
getProperty(person, 'age');   // OK, возвращает number
getProperty(person, 'email'); // Ошибка: 'email' не в ключах person

5. Множественные ограничения (Intersection)

interface HasName {
  name: string;
}

interface HasAge {
  age: number;
}

// Требует оба интерфейса
function describePerson<T extends HasName & HasAge>(person: T): string {
  return `${person.name} is ${person.age} years old`;
}

describePerson({ name: 'John', age: 30 });        // OK
describePerson({ name: 'John' });                 // Ошибка: age отсутствует

6. Условные типы и Generic

// Распределительные типы
type IsString<T> = T extends string ? true : false;

type A = IsString<'hello'>;   // true
type B = IsString<number>;    // false

// Практический пример
function processValue<T extends string | number>(
  value: T
): T extends string ? string : number {
  if (typeof value === 'string') {
    return value.toUpperCase() as any;
  }
  return (value * 2) as any;
}

7. Ограничение с использованием Record

// Объект с определённой структурой
function validateConfig<T extends Record<string, any>>(
  config: T
): T {
  for (const key in config) {
    if (config[key] === undefined) {
      throw new Error(`Missing required field: ${key}`);
    }
  }
  return config;
}

const config = validateConfig({ 
  api: 'https://api.example.com',
  timeout: 5000 
}); // OK

8. Default Generic параметры

Ограничение с дефолтным значением:

function createArray<T extends string | number = string>(value: T, count: number = 1): T[] {
  return Array(count).fill(value);
}

createArray('test');        // T = string
createArray('test', 3);     // T = string
createArray(42);            // T = number (явное ограничение)

// Практический пример с React компонентом
interface ComponentProps<T = {}> {
  data: T;
}

const MyComponent = <T extends object = {}>({ data }: ComponentProps<T>) => {
  return <div>{JSON.stringify(data)}</div>;
};

9. Сложный практический пример

type ApiResponse<T extends { id: string | number }> = {
  data: T;
  status: number;
  message: string;
};

function handleResponse<T extends { id: string | number }>(
  response: ApiResponse<T>
): T {
  if (response.status === 200) {
    return response.data;
  }
  throw new Error(response.message);
}

const user = { id: 1, name: 'John', email: 'john@example.com' };
const result = handleResponse({
  data: user,
  status: 200,
  message: 'Success'
});

// result имеет тип { id: number; name: string; email: string }

10. Generic Constraints для коллекций

// Только объекты, которые можно сериализовать
function serialize<T extends object>(obj: T): string {
  return JSON.stringify(obj);
}

// Массив с определённым типом элементов
function findDuplicate<T extends (string | number)[]>(arr: T): T[number] | undefined {
  const seen = new Set();
  for (const item of arr) {
    if (seen.has(item)) return item;
    seen.add(item);
  }
  return undefined;
}

findDuplicate([1, 2, 3, 2]);        // OK
findDuplicate(['a', 'b', 'a']);     // OK
findDuplicate([1, 'a', true]);      // Ошибка: boolean не в ограничении

Ограничение Generic параметров - это мощный инструмент для создания безопасного типизированного кода, который предотвращает ошибки на этапе разработки и улучшает читаемость и поддерживаемость приложения.

Как обеспечить поддержку шрифтов на старых устройствах? | PrepBro