Система типов TypeScript чрезвычайно мощна и позволяет перемещать и нарезать типы способами, невозможными ни на одном другом языке.
Это потому, что TypeScript разработан, чтобы позволить вам беспрепятственно работать с высокодинамичным языком, таким как JavaScript. Здесь мы рассмотрим несколько приемов перемещения типов в TypeScript.
Ключевая причина использовать их: вы меняете одну вещь, а все остальное обновляется автоматически, и вы получаете полезные ошибки, если что-то ломается, как в хорошо разработанной системе ограничений.
Если вы хотите переместить класс, у вас может возникнуть соблазн сделать следующее:
class Foo { }
var Bar = Foo;
var bar: Bar; // ОШИБКА: не могу найти имя 'Bar'
Это ошибка, потому что var
скопировал Foo
только в область объявления переменной, и поэтому вы не можете использовать Bar
в качестве описания типа. Правильный способ - использовать ключевое слово import
. Обратите внимание, что вы можете использовать ключевое слово import
таким образом, только если вы используете пространства имен или модули (подробнее об этом позже):
namespace importing {
export class Foo { }
}
import Bar = importing.Foo;
var bar: Bar; // Okay
Этот трюк с import
работает только для того что имеет и тип и переменную.
На самом деле вы можете использовать переменную в описании типа, используя оператор typeof
. Это позволяет вам сообщить компилятору, что одна переменная имеет тот же тип, что и другая. Вот пример, демонстрирующий это:
var foo = 123;
var bar: typeof foo; // `bar` имеет тот же тип, что и `foo` (здесь `number`)
bar = 456; // Okay
bar = '789'; // ОШИБКА: Тип `string` не может быть назначен типу `number`
Вы можете погрузиться в объект любого типа (кроме null), чтобы получить тип свойства:
class Foo {
foo: number; // член класса, тип которого мы хотим захватить
}
let bar: Foo['foo']; // `bar` имеет тип `number`
В качестве альтернативы, как и при захвате типа переменной, вы можете просто объявить переменную только для целей захвата типа:
// Только для захвата типа
declare let _foo: Foo;
// То же, что и раньше
let bar: typeof _foo.foo; // `bar` имеет тип `number`
Многие JavaScript библиотеки и фреймворки работают с необработанными строками JavaScript. Вы можете использовать переменные const
для захвата их типа, например:
// Захватываем и *тип* и *значение* магической строки:
const foo = "Hello World";
// Используем захваченный тип:
let bar: typeof foo;
// на bar может быть назначено только `Hello World`
bar = "Hello World"; // Okay!
bar = "anything else "; // Ошибка!
В этом примере bar
имеет литеральный тип Hello World
. Мы рассматриваем это подробнее в разделе литеральных типов.
Оператор keyof
позволяет вам захватывать тип по имени ключей. Например. вы можете использовать его для захвата типов имен ключей переменной, сначала получая её тип с помощью typeof
:
const colors = {
red: 'reddish',
blue: 'bluish'
}
type Colors = keyof typeof colors;
let color: Colors; // тоже самое что и let color: "red" | "blue"
color = 'red'; // okay
color = 'blue'; // okay
color = 'anythingElse'; // Ошибка: Тип '"anythingElse"' не возможно присвоить типу '"red" | "blue"'
Это позволяет вам легко создавать такие вещи, как строковые перечисления + константы, как вы только что видели в приведенном выше примере.