Flow протык TypeScript у 2026 годзе: суперасленне сынтаксісу і строгейшыя пераканаленыя
Дазнайцеся, як синтаксіс Flow тепер падобаецца сынтаксісу TypeScript, а таксама пра ўнікальныя выразы падбору, типы, спецыфічныя для React, і багі пад час выканання, якія TypeScript працягвае не з’явіць, але Flow выкрывае.
Да 2026 году Flow развіваўся па трох важлівых напрамках:
- Яго синтаксіс зараз значнаю часткай збігаецца з синтаксісам TypeScript: разработчыкі, які вже знаюць TypeScript, зможу распазнаваць большасць таго, што робіць Flow.
- Ён праставляе певныя можлівасці, якіх ўсё ще не хапае TypeScript: найболей выдатныя з іх — цэе выразы
matchа таксама спецыяльныя конструкцііcomponent,hookіrendersдля React. - Калі два системы типавання не пагоджуюцца, Flow зазвычай выбірае болей строгі варыянт: ён пазначае шаблоны, якія дозволяе TypeScript, але якія могу спрычыніць проблемы пад час выконання, таямніча зіпсаваць даныя або створыць тонкія логічныя памылкі.
Синтаксіс Flow і TypeScript зблізіўся
Пагляньце на фрагмент нижэй — чы можаце вы сказаць, це Flow чы TypeScript? Оерагваздо, не можаце.
type User = {
readonly name: string,
readonly age: number,
readonly metadata: unknown,
};
function get<K extends keyof User>(user: User, key: K): User[K] {
return user[key];
}
declare const user: User;
const age: number = get(user, 'age');
Любыя людзі, які впэўнена працуюць з TypeScript, не пазнаюць тут нічога неспадзянанлівага. Этот прыклад выкарыстоўвае keyof, атрыбуты readonly, тип unknown, адсылку па індэксу через T[K] і генерыкі з абмежэнням за дапамою extends. Flow таксама падтрымляе умовныя типы, картаваныя типы, захоўнікі типаў і as const, чыста наследуючы інструментарый TypeScript.
У рэштце гэтага артыкула акцэнт ставіцца на тыя аспекты, дзе Flow праходзіць да большых рэзультатаў, чым TypeScript.
Функцыі, якія є толькі у Flow
Ёсць можлівасці, якія існуюць у Flow, але не маюць адпаведніка ў TypeScript.
Выразы і запэўнення match
Flow адказвае канструкцыяю match для падабрання шаблонаў у вачынку. Кампайляр перагледвае яе абоўсюдна і дазваляе вам безпасэродзейна расклаць значэнні як частку процесу падабрання. Якщо вы забудзеце адмаўіцца якому-небудзь кэсу — напрыклад, type: 'remove' — match пакажае гэта і сказае вам точна, што не хватает.
type Action =
| {type: 'add', text: string}
| {type: 'toggle', id: string}
| {type: 'remove', id: string};
declare const action: Action;
const description = match (action) { // ERROR: 'remove' case missing
{type: 'add', const text} => `Add: ${text}`,
{type: 'toggle', const id} => `Toggle ${id}`,
};
Таксама існуе форма match у вачынку, якая паводзіцца як switch, які не можа прыйсці да наступнага кэсу, і мае всі тыя ж можлівасці, што і версія ў вачынку.
React: component, hook, renders
- Сінтаксіс
component: спрацоўвае з компанетамі React як з вбудованым паняйом на рэвэле мовы. Праблемы прызначаюцца безпасэродзейна як іменаваныя параметры, а перагледчык типаў можа застосаваць правіла правільнасці, спецыфічныя для React.
renders типы: дазваляюць вам апісаць, як компаненты складаюцца адзін з іншым. Системы дизайна та бібліятэкі компанентаў можуць точна прызначыць, што можа быць прийнятае ў споте і што можа быць створана компанентам, а калькюлятор прыменяе гэтыя правіла нават праз компаненты-обгорткі.hook сынтаксіс: пазначае хукі як самастоятельны, адзінаковы тип, аддзелены ад звычайных функцый. Flow вбудоввае Правіла React безпосередна ў свой калькюлятор типаў, выявляючы умовныя вызывы хуків, памешанне хукіў з звычайнымі функцыйямі і небезпечную мутацыю значэння, якое вяртае хук пад час рендара — усё гэта без неабходнасці наявнасці окалічнага плагіна ESLint.component Header(text: string, color: string) {
return <div style={{color}}>{text}</div>;
}
component MainHeader(text: string) renders Header {
return <Header text={text} color="red" />;
}
component Layout(header: renders Header) {
return <div>
{header}
<section>Content</section>
</div>;
}
const ok = <Layout header={<MainHeader text="Flow" />} />;
const bad = <Layout header={<footer />} />; // ERROR
Чатыры збоі пад час выканання, якія TypeScript не фіксуе — але Flow даўжына
Хтоце ў гэтым месца два системы типаў справжнім чынам разлічаюцца. Кожны прыклад нижэй праходзіць пераканальванне типаў у TypeScript 6.0.3 у режыме strict, пры тым як все ж такі не функцыонуе пад час выканання.
- Выявленне метода з экземпляра прыводзіць да таго, што ў TypeScript зникае яго прыяўленне
this
class Counter {
count: number = 0;
increment(): number {
return ++this.count;
}
}
const counter = new Counter();
const tick = counter.increment; // TS accepts. Flow rejects.
tick(); // Runtime crash! `this` is undefined inside `increment`
Калі вы выявляеце counter.increment з об’екта counter, ён больш не прыяўлены да яго — таму калі пазней вызваць його як tick(), значэнне this будзе undefined, і ++this.count выклікае адхыленне. TypeScript спрацьвоўвае выявлёны метод як звычную функцію і дазваляе ўваходзець яго без жадных заўважэнняў. Flow, на протываце, адхоўляе такое выявленне самэй у момент, калі зникае прыяўленне this.
- TypeScript дазваляе додатковыя атрыбуты праскочыць через непрямое прызначэнне
type Prices = {apple: number, banana: number};
const items = {apple: 1.5, banana: 0.5, sample: "free"};
const prices: Prices = items; // TS accepts. Flow rejects.
Object.values(prices).map(
price => price.toFixed(2), // Runtime crash! `sample` isn't a number
);
Тэкнічна частка типаў об’ектаў у TypeScript дазволяе наявнасць дадатковых атрыбутаў. «Перакананне ў занадто большым атрыбуте», якое зазвычай фіксуе ўсё, што на кшталт {apple: 1.5, sample: "free"}, працюе толькі тады, калі вы прызначаеце літерал об’екта безпосередня. Якщо той самы значэнне прабівае через проміжную зменную, гэта перакананне больш не дзейсніцца — таму атрыбут sample праходзіць непазначаны. Тэплівыя типы об’ектаў за замовчаннем є точнымі, тое значыць дадатковыя атрыбуты відхіляюцца, незалежна ад таго, як значэнне доходзіць да свайго месца.
- TypeScript дазволяе болей шырокі тип падставіць у вужэйшы зменны массив
// TypeScript: accepted.
function appendError(errs: Array<string | Error>) {
errs.push(new Error("oops"));
}
const errors: Array<string> = [];
appendError(errors); // TS accepts. Flow rejects.
errors[0].toUpperCase(); // Runtime crash! `errors[0]` isn't a string
Пакалькі ў TypeScript мутабельныя массивы спрацоўваюць як каваріантныя, таму Array<string> лічыцца падтыпам Array<string | Error>. Гэта значыць, што вызов прыймаецца, і вызов push унутры appendError прыводзіць да дадзення Error у массив, пра які вызывач супакоўваўся, што ён мае толькі string-ы элементы. Flow узбегае гэтага, спрацоўваючы мутабельныя массивы як інваріантныя, блакуючы расшырэнне працэсу адразу ў месцы вызову. Якщо функцыя насправды не патрабуе мутаваціўваць свой вхід, замена параметра на ReadonlyArray<string | Error> пачынаець усунуць рызык цэлком, адкуль ўніверсальнасць стае безнэпакойной.
- TypeScript не пераканальваецца, калі самэй функцыя типавага аховніка насправды выканае
// TypeScript: accepted, but this body is true for numbers, not strings.
function isString(x: unknown): x is string {
return typeof x === "number"; // TS accepts. Flow rejects.
}
const data: unknown = 1;
if (isString(data)) {
data.toUpperCase(); // Runtime crash! `data` isn't a string
}
TypeScript перакантролеўвае толькі заявленыя параметры типавога прадиката — ён ніколі не пераглядае, што насправды вяртае тэла функцыі. Flow перакантролеўвае оба направленні: кожна запаведзь return павінна даслівна прыводзіць да цэльовага типу, а ветка else павінна правильна адклеіць гэты тип. У результате Flow адхоўляе прадикаты, логіка якіх не адпавядае таму, што яны ствараюцься для перакантролеўвання.
Прачытайце цэлую параду
Для шырэйшага комплекту прыкладоў на сабе сторонцы дакументацыі Flow ёсць раслогы матэрыял, які параграф за параграфам поручывае два языкі, апісваючы болей чым двадцать дапаможных касоў паляглых на тым, што паказана тут: пазірце на аднараднік.
Связаная літэратура
- Стандарты Full-Stack JavaScript у 2026 году: TypeScript, RSC і іншыя — Адказвае, чаму TypeScript, React Server Components і болей простыя методы карбавання стану сталі стандартным комплектам для команд, якія працуюць з JavaScript у 2026 году.
- Праекты TC39 у 2026 году: декоратары, Temporal і Signals — адказанне — Практычны аналіз трох праектаў TC39 — натывных декоратароў, API Temporal і Signals — і таго, што яны значаюць для разработчыкаў Full-Stack JavaScript і TypeScript.