Tajpaj Tipoj

Kiel plej bone tajpi opojn en Typescript 4.2 kaj pli posta

Pli proksima rigardo al Tajpaj tajpoj

Kiel rapida memorigilo, opo en sia plej baza difino estas nur datuma strukturo, kiu konsistas el multaj partoj. Kun la uzo de opoj en programlingvoj, kiel Typescript, ankaŭ gravas rimarki, ke la datumoj estas plej ofte ordigitaj.

Simpla ekzemplo montras kiel opoj estas difinitaj en Tajposkripto.

// 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"];

Opoj kun nedevigaj elementoj

Ĉar Tajpskribo pliboniĝis kun la tempo, ankaŭ ĝia efektivigo de opoj. Vi ne nur devas difini elementojn, kiuj devas esti devigaj. Vi nun povas ankaŭ tajpi elementojn laŭvole. Se vi ne scias, Typescript uzas la demandosignon kiel ĝenerala simbolo por difini elementojn kiel nedevigajn, kio signifas, ke ili povas esti haveblaj dum rultempo, sed ne devas.

Alia ekzemplo montras, kion mi celas per tio.

// 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"];

Ripozaj elementoj en tajpaj tipoj

Kun ripozaj elementoj, vi havas tre potencan tipon ĉe la mano, kiu markas ĉiujn sekvajn elementojn en la opo de difinita tipo. Do diru, ke vi havas opon kun du elementoj kaj la duan difinitan kiel ripozan elementon, vi povas tiam provizi 2 + n elementojn dum rultempo al ĉi tiu opvariablo.

Por malvastigi la difinon, ĝis antaŭ nelonge tia elemento estis permesita nur ĉe la fino de opo. Ĉi tio havas sencon, ĉar ĉi tio permesas al vi provizi ajnan nombron da elementoj dum rultempa speco de la ripozo, sed malfaciligus la aferojn distingi tiam inter la ripozelemento kaj unu plia, alia tajpita ero.

// 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"];

Gvida aŭ meza ripozelemento en opspecoj

Antaŭenigante la ripozan elementon por opoj, vi povas krei eĉ pli kompleksajn efektivigojn ekde tajpado 4.2. Kaj mi devas pardonpeti ĉi tie: nur kelkajn frazojn frue, mi skribis kiel estas devige uzi ripozan elementon nur kiel la lastan. Ĉi tiu limigo efektive ne plu veras ekde Tajpskribo 4.2, ĉar vi nun povas meti ripozajn elementojn preskaŭ ie ajn en opo.

Sed kun nur kelkaj limigoj, Typescript nun provizas tre belan sintakson por progresintaj opoj. Ripozelementoj povas okazi ie ajn ene de opo kondiĉe ke ili konformas al la sekvaj du reguloj

  • ĝin ne sekvas nedeviga elemento
  • neniu alia ripozelemento sekvas la unuan

Antaŭ ol paroli tro multe da teorio, ni vidu ekzemplon.

// 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.

La cetera elemento de ĉi tiu artikolo

Fermante ĉi tiun kompaktan gvidilon pri opoj en Typescript, ni rigardis la bazan efektivigon kaj poste trapasis iujn pli progresintajn ekzemplojn por vidi kiel Typescript permesas tre flekseblan tipan sistemon kiam temas pri opoj. Mi esperas, ke vi ĝuis la artikolon kaj se vi scivolas lerni pli, rigardu la sugestitajn afiŝojn aliajn sube.