Strażnicy typów TypeScript

Type guards to potężna funkcja w TypeScript, która umożliwia programistom wykonywanie kontroli w czasie wykonywania w celu zawężenia typu zmiennej. Zapewnia to dokładniejsze informacje o typie, co prowadzi do bezpieczniejszego i bardziej przewidywalnego kodu. W tym artykule omówiono, czym są type guards i jak skutecznie ich używać.

Czym są Type Guards?

Strażnicy typów to wyrażenia, które wykonują kontrole w czasie wykonywania i pozwalają TypeScript na wnioskowanie bardziej szczegółowego typu zmiennej. Pomagają w rozróżnianiu różnych typów, szczególnie w przypadku typów unii. Strażnicy typów mogą być implementowani przy użyciu różnych technik, w tym:

  • Predykaty typu zdefiniowanego przez użytkownika
  • Asercje typu
  • Sprawdzanie instancji
  • Korzystanie z operatora typeof
  • Używanie operatora in

Predykaty typu zdefiniowanego przez użytkownika

Predykaty typu zdefiniowanego przez użytkownika to funkcje, które zwracają wartość logiczną i mają specjalny typ zwracany, który wskazuje typ sprawdzanej zmiennej. Oto jak je utworzyć i używać:

function isString(value: any): value is string {
  return typeof value === 'string';
}

function printString(value: any) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log('Not a string');
  }
}

W powyższym przykładzie isString to zdefiniowany przez użytkownika predykat typu, który pomaga TypeScript zrozumieć, że value jest ciągiem znaków w bloku if.

Asercje typu

Asercje typu mówią TypeScript, aby traktował zmienną jako określony typ. Ta metoda nie wykonuje sprawdzenia w czasie wykonywania, ale informuje kompilator TypeScript o typie. Na przykład:

function printLength(value: any) {
  console.log((value as string).length); // Assert value is a string
}

W tym przykładzie value as string informuje TypeScript, że ma założyć, że value jest ciągiem znaków, bez wykonywania sprawdzenia w czasie wykonywania.

Sprawdzanie instancji

Sprawdzanie instancji służy do określania, czy obiekt jest instancją określonej klasy. Jest to przydatne do zawężania typów podczas pracy z klasami:

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

class Cat {
  meow() { console.log('Meow'); }
}

function speak(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark(); // TypeScript knows animal is a Dog here
  } else {
    animal.meow(); // TypeScript knows animal is a Cat here
  }
}

W tym przykładzie operator instanceof pomaga TypeScript wywnioskować typ animal na podstawie jego klasy.

Korzystanie z operatora typeof

Operatora typeof można używać do sprawdzania typów pierwotnych, takich jak string, number i boolean:

function processValue(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log(value.toFixed(2)); // TypeScript knows value is a number here
  }
}

Tutaj typeof służy do sprawdzenia, czy value jest string czy number i odpowiednio zawęża typ.

Używanie operatora in

Operator in sprawdza obecność właściwości w obiekcie. Jest to przydatne do rozróżniania typów, które mają wspólne właściwości:

interface Bird {
  fly: () => void;
}

interface Fish {
  swim: () => void;
}

function move(creature: Bird | Fish) {
  if ('fly' in creature) {
    creature.fly(); // TypeScript knows creature is a Bird here
  } else {
    creature.swim(); // TypeScript knows creature is a Fish here
  }
}

W tym przykładzie operator in pomaga TypeScript określić, czy creature jest Bird czy Fish na podstawie obecności metody.

Wniosek

TypeScript type guards to niezbędne narzędzia do pracy z typami w elastyczny i bezpieczny sposób. Umożliwiają one dokładniejsze sprawdzanie typów i mogą zapobiegać błędom w czasie wykonywania, zapewniając, że w różnych scenariuszach używany jest właściwy typ. Zrozumienie i skuteczne używanie type guards może prowadzić do bardziej wytrzymałego i łatwego w utrzymaniu kodu TypeScript.