Типы кортежей машинописного текста

Как лучше всего вводить кортежи в Typescript 4.2 и новее

Более пристальный взгляд на кортежи Typescript

Напоминаем, что кортеж в его самом базовом определении - это просто структура данных, состоящая из нескольких частей. В контексте использования кортежей в языках программирования, таких как Typescript, также важно отметить, что данные наиболее часто упорядочиваются.

Простой пример показывает, как кортежи определяются в Typescript.

// This tuple is defined as a set
// of two numbers.
const scores: [number, number] = [1, 2];

// For comparison, this tuple consists
// of three elements, each of a different
// type. Not that the ordered nature of
// tuples in TS becomes very clear here.
const result: [string, number, boolean] = ["id", 101, false];

// And as a "nice-to-know", you can even
// provide lables for the tuple elements.
// This doesn't have any effect on the typesystem
// itself and only (may) improve documentation.
const output: [id: number, name: string] = [101, "Tom"];

Кортежи с необязательными элементами

По мере того, как Typescript со временем становился лучше, улучшалась и его реализация кортежей. Вам не нужно только определять элементы, которые должны быть обязательными. Теперь вы также можете вводить элементы как необязательные. Если вы не знаете, Typescript использует вопросительный знак в качестве общего символа для определения элементов как необязательных, что означает, что они могут быть доступны во время выполнения, но не обязательно.

Другой пример демонстрирует, что я имею в виду.

// Similar to our previous example, but in this
// case the the tuple's last element doesn't have
// to be provided (or can be undefined at runtime).
type Tuple = [id: number, name?: string];

const a: Tuple = [101];
const b: Tuple = [42, "Tom"];

Остальные элементы в кортежах Typescript

С остальными элементами у вас под рукой очень мощный тип, который маркирует все следующие элементы в кортеже данного типа. Скажем, у вас есть кортеж с двумя элементами, а второй определен как элемент отдыха, затем вы можете предоставить 2 + n элементов во время выполнения этой переменной кортежа.

Чтобы сузить определение, до недавнего времени такой элемент разрешался только в конце кортежа. Это имеет смысл, так как это позволяет вам предоставлять любое количество элементов во время выполнения типа rest, но очень усложняет различение между остальным элементом и еще одним типом.

// This example might be a tuple type
// for a CLI similar to Node.js. The first
// two elements are system-internal.
//
// Starting from the 3rd element, a user can
// provide as much arguments as desired, yet
// we can still cleanly handle it with TS. Nice!
let input: [number, boolean, ...string[]];

// Just to show that we really can provide any
// number of rest elements, including 0.
e = [0, false, "max-cache", "1024", "debug", "false"];
e = [0, false];
e = [0, false, "verbose"];

Ведущий или средний элемент остатка в типах кортежей

Продвигая остальной элемент для кортежей, вы можете создавать еще более сложные реализации, так как был выпущен Typescript 4.2. И здесь я должен извиниться: всего на несколько предложений раньше, я написал, что обязательно использовать элемент отдыха только в качестве последнего. Это ограничение больше не действует, начиная с Typescript 4.2, так как теперь вы можете размещать остальные элементы практически в любом месте кортежа.

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

  • за ним не следует необязательный элемент
  • никакой другой элемент отдыха не следует за первым

Прежде чем говорить слишком много теории, давайте посмотрим на примере.

// And here comes the fancy part: rest elements
// *not only* at the end of a tuple.
// 
// Note: this example is taken directly from the
// TS documentation. For more details, check out the
// links in the addendum.
let foo: [...string[], number];

foo = [123];
foo = ["hello", 123];
foo = ["hello!", "hello!", "hello!", 123];

let bar: [boolean, ...string[], boolean];

bar = [true, false];
bar = [true, "some text", false];
bar = [true, "some", "separated", "text", false];

// And here's an example that shows how the
// type system would catch your errors:
interface Clown { /*...*/ }
interface Joker { /*...*/ }

let StealersWheel: [...Clown[], "me", ...Joker[]];
//                                    ~~~~~~~~~~ Error!
// A rest element cannot follow another rest element.

let StringsAndMaybeBoolean: [...string[], boolean?];
//                                        ~~~~~~~~ Error!
// An optional element cannot follow a rest element.

Остальной элемент этой статьи

Завершая это краткое руководство по кортежам в Typescript, мы рассмотрели базовую реализацию, а затем рассмотрели несколько более сложных примеров, чтобы увидеть, как Typescript позволяет создать очень гибкую систему типов, когда дело касается кортежей. Надеюсь, вам понравилась статья, и если вам интересно узнать больше, ознакомьтесь с предложенными постами и другими ниже.

Предложения

Связанные

Приложение

Языки