TypeScript — это не только про аннотацию типов. Примеры из практики

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Всем привет, меня зовут Виталий, я сотрудничаю с компанией Itera и мы с вами уже знакомы по моей прошлой статье о Дия Сити. Но сегодня я не хочу говорить о политике или бизнесе. Сегодня я хочу поговорить о TypeScript и зачем он нужен.

Казалось бы, в 2021 году говорить об этом несколько поздновато — технология уже известна и популярна. Однако несмотря на это, много где он используется вполсилы. Простейшая аннотация типов, проверка на null и всё. Поэтому я принес несколько интересных, сугубо практических кейсов, чтобы показать, что TS может куда больше.

Кратенько о себе: с TS работаю больше 5 лет, любил, страдал (до ненависти дело так и не дошло, но бывало матерно) и вот сейчас на стадии приятелей. Если готовы — берите кофе, впереди будет мало текста и много кода. Мы поговорим о подмножествах, проекциях и динамическом выведении типов.

Сужение примитивов

Однажды, прогуливаясь по морскому порту, Ученик спросил у Мастера: — Зачем нужен TypeScript, если у нас есть здравый смысл? В ответ Мастер указал на только что пришвартовавшихся иностранных моряков, и попросил Ученика поприветствовать их. Ученик с достоинством поклонился в сторону новоприбывших. Оскорбленные моряки набросились на Ученика и избили его.

Давайте начнем с простого. Представьте себе, что у нас есть некая функция, которая принимает на вход ключ, достает из словаря по ключу перевод и возвращает его. Какой будет тип этого ключа? Скорее всего — string. Но понятно, что не каждый string является допустимым ключом — нам точно не нужна вся британская энциклопедия, да и опечатки никто не отменял.

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

И тут у TypeScript есть очень элегантное решение — если тебе не нужен весь string, то скажи об этом честно и просто объяви подмножество:

type TranslationKey = 'grey';
function translate(key: TranslationKey){...}

Благодаря этому приему мы получаем сразу несколько преимуществ:

  • Что попало в метод, уже не передать — мы защищены от опечаток и ключей, к которым еще не готовы на этапе билда.
  • Когда какой-то ключ поменяется (grey -> gray), мы сразу увидим все места, где нужно обновить код.
  • Работает IntelliSense — использовать ключи стало намного проще, не надо каждый раз лезть и искать, как же этот landing_big_ad_imageblock_subheder пишется (кстати, вы заметили опечатку?).

Этот же прием можно использовать, если мы хотим провалидировать некое значение перед использованием:

type Email = string;
const sendEmail = (email: Email)=> {...}
sendEmail('[email protected]'); // fails

Когда мы попытаемся передать в метод sendEmail любую строку, TS заставит нас ее проверить, например, написав guard:

// don't use in production please
const isValidEmail = (maybeEmail: unknown): maybeEmail is Email =>
typeof maybeEmail === "string" && /^\[email protected]\S+$/.test(maybeEmail);

Если вам интересны подробности о том, как это работает — вот ссылка на документацию.

Производные от типов

Однажды, уже спускаясь с высокой горы, Ученик спросил у Мастера: — зачем нужен TypeScript, если его не существует в RunTime? В ответ Мастер толкнул Ученика и тот, не устояв на ногах, с криком покатился вниз. Не дожидаясь, пока крики стихнут, Мастер продолжил путь.

С примитивами мы разобрались, теперь я хочу показать еще одну возможность, которой часто пользуюсь — создание нового типа на основе существующего. В ООП мы обычно используем наследование, а TypeScript позволяет трансформировать одни типы в другие. Наверняка вы уже использовали тип Partial<T> или Required<T>, которые идут сразу из коробки. Но кроме встроенных типов мы можем создавать и свои, например, вот так:

type NotEmptyString = string;
type User = { name: NotEmptyString };
type Dto<T> = { [key in keyof T]: unknown };
type UserDto = Dto<User>;

Сначала я описал доменную модель, с которой готов работать. Для этого примера я создал тип User с единственным полем name, которое должно содержать не пустую строку. Но, поскольку я не очень-то доверяю постороннему сервису, из которого приходят данные, я хочу ответ от сервера провалидировать. Для этого я создал производный тип UserDto, в котором честно объявил, что понятия не имею, что же нам пришлют. Теперь я, а также все, кто придет после, будем вынуждены проверить данные перед их использованием.

Естественно, с помощью этого подхода можно написать и схему валидатора.

Шаг 1. Создаем обобщенный тип, который содержит все те же поля, что и будущий тип T, а значениями будут функции, которые принимает аргумент неизвестного типа, и возвращают признак принадлежности аргумента заданному типу.

type DtoValidator<T> = {
  [key in keyof T]: (v: unknown) => v is T[key];
};

Шаг 2. Пишем валидатор в форме guard-а, в котором проверяем переданный аргумент. Если он удовлетворяет заданные условия, мы признаем, что он принадлежит типу NotEmptyString.

 const isNotEmptyString = (v: unknown): v is NotEmptyString =>
  typeof v === "string" && v.length > 0;

Шаг 3. Собираем все вместе в схему валидации. Обратите внимание на то, что теперь уже TS будет следить за тем, чтобы в схеме все поля были описаны и корректно заполнены. Если мы что-то упустим, TypeScript выдаст ошибку.

const userValidator: DtoValidator<User> = {
  name: isNotEmptyString,
};

Самое прекрасное здесь то, что когда мы расширим доменную модель новым полем, TS автоматически напомнит нам, что это поле тоже нужно взболтать проверить.

На моем проекте мы используем этот подход для валидации форм. Есть модель формы, а на ее основе строится модель валидатора. Когда поля формы меняются (что периодически бывает), TypeScript подсказывает, где мы прошляпили.

Динамическая модификация типов

Однажды, гуляя ухоженным монастырским парком, Ученик спросил у Мастера: — Зачем нужен TypeScript, если его можно заменить на JSDoc? В ответ Мастер указал на пирамиду стоящих друг на друге камней и попросил вопрошающего выбить нижний камень. Ученик всей силой навалился на основание. Увидев, как шатается их любимая скульптура, монахи избили Ученика палками.

Этот трюк может быть особенно актуален, если вы используете контексты в React, но сама идея будет работать везде. TS позволяет выводить новые типы «на лету», исходя из данных, которые вы передаете. Это может звучать немного запутанно, так что давайте посмотрим на примере.

Напишем функцию, которая приветствует пользователя:

type User = { firstName: string };
type Greetings = { greetingText: string };
const getGreetings = ({ firstName, greetingText }: User & Greetings) =>
  `${greetingText}, ${firstName}!`;

Очевидно, что имя пользователя у нас появится в рантайме, а вот текст самого приветствия может быть статичным. Можно написать функцию высшего порядка, которая будет внедрять greetingText в getGreetings.

const greeterFactory = () => (user: User) =>
  getGreetings({ ...user, greetingText: "Hello" });
const greeter = greeterFactory();
greeter({ firstName: "Vitalii" });

Все хорошо, но это частное решение, а хотелось бы иметь общее, которое бы:

  • Работало с произвольными типами.
  • Убирало из требуемого типа те поля, которые уже содержаться во внедренном объекте.

Наивная реализация могла бы выглядеть так:

function factory<TModel, TResult, TInjected extends Partial<TModel>>(
  callback: (m: TModel) => TResult,
  inject: TInjected
) {
  return (m: Omit<TModel, keyof TInjected>) => callback({ ...inject, ...m });
}

Однако компилироваться она не будет, потому что я допустил любопытную ошибку:

factory((m: { greeting: string; name: string }) => m.name, {
  greeting: "hello",
  name: "Vitalii",
})("Joker");

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

// I am not a monster
function factory<
  TCallback extends (arg: any) => any,
  TModel extends Parameters<TCallback>[0],
  TInjected extends Partial<TModel>
>(callback: TCallback, injected: TInjected) {
  return function <TProps extends Omit<TModel, keyof TInjected>>(
	props: TProps extends object ? TProps : never
  ): ReturnType<TCallback> {
	return callback({ ...injected, ...props });
  };
}
 const greeter = (_: { greeting: string; name: string }) => "";
 // "Argument of type 'string' is not assignable to parameter of type 'never'"
const failed = factory(greeter, {
  greeting: "hello",
  name: "Vitalii",
})("Joker");
 // // Works with full IntelliSense support.
const working = factory(greeter, {
  greeting: "hello",
})({ name: "test" });

Теперь все работает, как ожидается, хотя есть нюанс. Во-первых, читается это сложно, хотя идея тут довольно простая и строится вокруг возможности TypeScript-а извлекать типы из функций и служебного типа Omit. А во-вторых, в рантайме, как в injected, так и в props, может попасть объект с куда большим количеством полей и это стоит иметь ввиду.

Для нас этот подход пригодился, когда мы писали свои коннекторы к хранилищу данных в React. В результате, в компонент нужно было передавать только те поля, которых нет в сторе, остальные он «возьмет» сам, а TypeScript проверит, что мы не забыли пробросить недостающие. Поскольку все объекты под нашим контролем, нюанс, о котором я упоминал, проблемой не был.

Итоги подведем

Как видите, TypeScript — это нечто большее, чем просто аннотация типов. Он позволяет создавать подмножества, проекции, выводить типы на лету и многое другое, о чем я не упоминал. Несмотря на то, что в runtime TypeScript отсутствует, правильно написанные типы упрощают разработку и могут уберечь от промахов.

С другой стороны, с виду очевидные решения на TypeScript не работают. Ошибки бывают непонятны и не очевидны, особенно в начале работы с языком (да и чего таить греха — потом тоже). Старт проекта тоже идет медленнее, так как нужно спроектировать и описать типы, а потом еще и исправить там, где ты промахнулся.

И все же, удобства, которые обеспечивает TypeScript, того стоят. Знакомить новых людей с проектом и даже самому возвращаться к модулю, с которым ты не работал хотя бы месяц — намного легче и приятнее. Главное — это сохранять баланс, как говорил главный персонаж одной очень философской игры. Если вы видите, что TS усложняет поддержку вашего кода — значит кто-то свернул не туда.

Всем хороших праздников!

👍ПодобаєтьсяСподобалось10
До обраногоВ обраному7
LinkedIn

Найкращі коментарі пропустити

...а я так и не понял — почему для статической проверки типов не взлетел ненавязчивый Flow
Тренды в программерской тусовке ничуть не рациональней чем в парижской моде...

Как по мне, для любого ЯП с дин типизацией возможности статического анализа типов должны такими и быть — аннотациями, или вкраплениями, которые ни к чему не принуждают, а могут использоваться по желанию, и в той степени в какой нужно для конкретных проектов и команды.

// @flow
function square(n: number): number {
  return n * n;
}

В php даже управление мягким/строгим приведением типов можно управлять — на уровне файла исходного кода

<?php
declare(strict_types = 1);
function getString(string $str) {
 var_dump($str);
}
$int = 12;
getString($int);
//Fatal error: Uncaught TypeError: Argument 1 passed to getString() must be of the type string, integer given...
и указывать типы где надо, а где не надо — то и не указывать

И в Питоне есть подобная штука typing — Support for type hints
Когда же говорят что TS это «всего лишь» надмножество JS, ай, оставьте

Что это за JS такой:

type DtoValidator<T> = {
  [key in keyof T]: (v: unknown) => v is T[key];
};
а такого, раз уже взялся TS для написания кода — будет много
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Щодо валідації email, теж зацікавився цим питанням і написав статтю catchts.com/email-validation . Можливо Вам буде цікаво.

Я коли прочитав Ваш код відразу зрозумів що бачив його на stackoverflow. Доречі цікава задачка з функцією factory.

Дякую за статтю, цікавий підхід з валідаторами.

...общаясь с фронтендерами в реале, на разных проектах, в разных ситуациях, и естественно куда корректнее чем на форумах, у меня сложилось ощущение что многие топящие за TS
едва осилившие по нескольким владиленовским курсам JS — с болью и муками сделавшие пару проектов — открывают для себя статическую типизацию.

примерно как мальчик влюбился в кривоногую, рябую, косоглазую и не очень умную девочку — и все радуются — взрослеет, вот она и Первая Любовь.
Но мальчику пока невдомек что каноны женской красоты — другие. от сам у захваті от собственного чувства, он ощущения что он уже небесах, и смотрит на скучных людишек в сиянии своего чувства.

TS тут вообще не причем, ни его достоинства, ни недостатки. Я вообще считаю Хейлсберга незаслужено обделенным внимания. Его должны бы знать как и Страуструпа.

но адепты, адепты... ух! :)

About two years ago I noticed something. I was depending less and less on the type system for safety. My unit tests were preventing me from making type errors.
Now I am back programming in Java because the projects I’m working on call for it.
But I can’t deny that I feel the tug of the dynamically typed languages. I wish I was programming in Ruby or Python, or even Smalltalk.
by Robert C. Martin www.artima.com/...​/viewpost.jsp?thread=4639

The older I get, the more I appreciate dynamic languages. Fuck, I said it. Fight me.
“Drunk Post: Things I’ve learned as a Sr Engineer”
old.reddit.com/...​learned_as_a_sr_engineer

My unit tests were preventing me from making type errors.

Да да. Делать мне нехер вместо работы сидеть бесполезные тесты писать.
Зы Ухепта это ж дядя боб. Сразу в игнор этого дурачка. Почитай дядю боба и сделай наоборот как говориться.

Делать мне нехер вместо работы сидеть бесполезные тесты писать.

Ох уж этот Украинский галерный аутсорс :-))

Делать мне нехер вместо работы сидеть бесполезные тесты писать.

не пишите, кто ж неволит
я ж тоже пишу только те и тогда когда мне надо.
независимо от ЯП

Да да. Делать мне нехер вместо работы сидеть бесполезные тесты писать.

А бесполезные тайпинги есть хер писать?)

Нахрена? В 95% случаев есть же var.

Раз уже ссылаетесь на старину Боба, то он чем старее, тем более гладиолус. Приведу пару его цитат из куда более свежего:

My favorite language of all, the language that I think will outlast all the others, the language that I believe will eventually become the standard language that all programmers use...

...is Lisp.

And then, a decade ago I found SICP. And after that I found Clojure. Clojure is a Lisp that rides on top of the Java ecosystem (and does not have CARs or CDRs, or CADADAADR s).

I wasn’t convinced right away. It took a few years. But after the usual stumbling around and frustration, I began to realize that this language was the easiest, most elegant, least imposing language I had ever used — and not by a small margin.

blog.cleancoder.com/...​019/08/22/WhyClojure.html

По поводу статической vs динамической типизации и тестов:

If you compare the two functions that Mark and I wrote (and if you understand Haskell, which I don’t) I think you’ll find that the two implementations are somewhat similar. The testing strategies we employed were, however, very different.

The tests I wrote show that I was concerned almost entirely with the desired behavior of the function. The tests walk that behavior forward one small step at a time using the TDD style.

Mark, however, was far more concerned with expressing correctness in terms of generic types. The vast majority of his thought process was consumed with the type structure that properly represented the problem. He then verified behaviors with property-based QuickCheck style tests, and after-the-fact tests.

Which is better?

„Answering that question with specificity is above my pay grade.” — Barack Obama.

Which of us wound up with fewer tests? In either case I think the four base assertions are adequate. However, as part of the process I wrote 8 assertions and Mark wrote two property-based QuickCheck tests, and three after-the-fact regression tests. Does that amount to 5 vs. 8? Or do those QuickCheck tests count for more? I don’t know. I’ll let you decide.

blog.cleancoder.com/...​/06/08/TestsAndTypes.html

При всех современных тулзах: линтерах и продвинутых IDE можно вполне себе успешно писать и код с динамической типизацией. Да, при этом покрытие тестами по поведению и входным данным должно быть куда более серьезное чем в аналогичных системах со статической типизацией, так как нужно учитывать что может прийти null,nil,NaN,object,any и т.п. Читаемость и сопровождаемость систем с дин. тип. в значительной степени будет зависить от соблюдения коде конвеншинов, опыта разработчиков и тулзов по отлавливанию ведьм. Статическая типизация, с другой стороны, позволяет на уровне типов отсечь невалидные данные, повысить самодокументируемость кода и меньше зависить от тулзов. ЯП со стат. типизацией и улучшеным выводом типов (Haskell, F#, Idris) к тому же делают аннотацию вообще не нужной в большинстве случаев и код выглядит примерно как в яп с дин. типизацией.

Гибкость джаваскрипта позволяет делать многие вещи и писать мультипарадигменно. Обратная сторона медали, это то что с таким же успехом джс позволяет легко снести себе бошку. Стать действительно хорошим джаваскрипт разработчиком (или любого другого яп с дин. типизацией) и писать эффективнй код, требует много больше времени и практики.
TypeScript в этом плане видится как попытка все-таки не снести себе бошку и сделать жизнь разрабов легче, а код более самодокументируемым.

Обратная сторона медали, это то что с таким же успехом джс позволяет легко снести себе бошку.

Си — это инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво. Брайан Керниган
не страшно жить в мире где ладно там сервера на линухе, а ембедед этой бритвой сделан?

ну а веб с пыхой на бекенде — не страшно?

Раз уже ссылаетесь на старину Боба,

это для тех для кого он авторитет — молодежи, которая изучала джс по ютьюбу, и открыла рот от изумления увидев первый в своей жизни ЯП с статической типизацией :)

Си — это инструмент, острый, как бритва: с его помощью можно создать и элегантную программу, и кровавое месиво. Брайан Керниган
не страшно жить в мире где ладно там сервера на линухе, а ембедед этой бритвой сделан?

Все верно. Но система типов в Си или С++ достаточно базовая по сравнению с той же Java/C# - использование указателей, более примитивные абстаркции, нет проверки на граничные значения в тех же массивах и т.п. И да, на C++ писать сложнее и времязатратнее, но там где нужна производительность и высокий уровень контроля самое оно.
Конечно есть контр-пример — Haskell — писать еще сложенее и порог входа. Но тут уже другие гарантии от компилятора по типам... это скорей не бритва, а топорик с резиновой рукоятью и к нему перчатки из стекловолокна.

ну а веб с пыхой на бекенде — не страшно?

Страшно, вот и переписываем на C# и Angular/TypeScript :)

Но система типов в Си или С++ достаточно базовая

и однако ж, поди ж ты, пишут и до сих пор на них.
ужас?

по сравнению с той же Java/C#

да, GC рулит.

Конечно есть контр-пример — Haskell — писать еще сложенее и порог входа.

странно, типы ж — это так удобно, так здорово, не то что ООП, которое годы и годы учить.
интерны за год осваивают ФП!

Страшно, вот и переписываем на C# :)

у кого какой опыт.
я уже встречал проекты которые с джавы на пыху переписывают :)

с полгода назад даже была статья от одного лида, из команды неслабой в США компании, как они с джавы в пыху ушли.

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

Оно ж как в присказке одного миллионера
Я вам расскажу про любой миллион как я его заработал. Кроме первого.

Так и публично, в докладах — почти никогда не услышишь как и почему принималось техническое решение.

и однако ж, поди ж ты, пишут и до сих на них.
ужас?

Не, пямятник при жизни им.

да, GC рулит

Ну не единым же GC

странно, типы ж — это так удобно, так здорово, не то что ООП, которое годы и годы учить.
интерны за год осваивают ФП!

Так себе подкол :) Осваивают, но не Haskell же наскоком.. OCaml-овский F# или Lisp почеловечнее будет. Это как освоить C++ (или скорее C#) за год на базе знаний скажем по Turbo Pascal — писать код уже можно, но под присмотром. Как аналогия ООП программиста еще без знания SOLID и паттернов вдоль и поперек.
pbs.twimg.com/...​t_?format=png&name=medium

А что после SOLID-то ? Правильно, ФП :)
blog.ploeh.dk/...​-next-step-is-functional

у какого какой опыт.
я уже встречал проекты которые с джавы на пыху переписывают :)

с полгода назад даже была статья от одного лида, из команды неслабой в США компании, как они с джавы в пыху ушли.

Интересно какая мотивация и rationale?

Ну не единым же GC

единым.
Джава и сейчас не очень крутой язык,. а на старте была посмешищем.
и т.д. историю ЯП я уже столько раз пересказывал, что пора в серию статей собирать, да кто ж их читать будет... кому она нужна, история :)

OCaml-овский F# или Lisp почеловечнее будет.

да.
а вы откройте рейтинг Tiobe — и посмотрите где там F#, а где Scratch ;)

Интересно какая мотивация и rationale?

Та что и всегда:
Скорость разработки.
По этой же причине появлся и выжил и COBOL и С и Java

и мне понятно почему скорость разработки на современном PHP выше чем на Джаве
как и на Ноде выше чем на Go — в тех же задачах

Секрет вы уже знаете, я тут в простынищах коментов его выдал ;)

общее правило — любые технология, метод, подход, способ X — что повышают скорость выживут.
А весьма вероятно станут — основными.
а никакой прямой корреляции с академичностью, правильностью, «думами математиков» этот X не имеет.

Никакая реклама академичностью не сделает метод, способ X — популярным
а сделает его популярным без всякой рекламы, и пусть весь академический мир плюется, тру инженеры брюзжат
Скорость разработки

общее правило — любые технология, метод, подход, способ X — что повышают скорость выживут.
А весьма вероятно станут — основными.
а никакой прямой корреляции с академичностью, правильностью, «думами математиков» этот X не имеет

Рейтинги в прогнозировании будущего ЯП это как гадание на кофейной гуще. Да и неблагодарное это дело. Где был пайтон в нулевых? Как появился в 1991, полз черепахой к успеху: С.С++, C#, Java и Ruby были всегда популярнее и долгими годами держали планку. Если верить дядюшке Бобу, популяция программистов удваивается каждые 5 лет. Следовательно мы имеем много нубиков которые обычно стартуют с JS и Python как самого быстро способа войти в айти. Ну и Scratch туда же :)
Тут корреляция с эффективностью ЯП весьма косвенная и неустойчивая.
Кол-во вакансий по C#/Java, Kotlin, Scala, Go меньше тоже не становится. Можно так же отметить что существующие Python/PHP/JavaScript проекты не самые интересные и прогрессивные с точки зрения tech. Да, сайтики, малость in-house софта, немного мэшин лернинга быстро своять позволяют, но всякие там Эриксоны, Фейсбуки, Гуглы и Мозилы выдают нечто вроде Erlang, Rust, Go вовсе не от хорошей эффективности яп с дин. типизацией. :)

Рейтинги в прогнозировании будущего ЯП это как гадание на кофейной гуще.

конечно.
но история развития уже есть, чтобы можно начать выявлять причины. задним умом. которым же все и крепки :)

Где был пайтон в нулевых? К

вот именно!
и? оглянитесь — и прикиньте — а почему он был тогда там, а сейчас — здесь? что было причиной?

С.С++, C#, Java и Ruby были всегда популярнее и долгими годами держали планку.

да, и давайте по каждому — а его вверх-вниз популярности — что толкало?

это ж знаете шутку
самые точные диагнозы ставит паталогоанатом. у нас же история языков — вполне публичная. надо просто — оглянуться, а не смотреть вперед, в будущее где «функциональное программирование зохавает весь мир!»
оглянуться надо вначале, прежде чем делать такие прогнозы :)

Тут корреляция с эффективностью ЯП весьма косвенная и неустойчивая.

я не говорил об эффективности ЯП.
я говорил о скорости разработки при использовании ЯП
и насчет неустойчивости примерчик бы

Кол-во вакансий

колво вакансий — это количество вакансий. работающих на каком либо ЯП, гуглящих и обсуждающих (это они делают рейтинг Tiobe) куда больше

проекты не самые интересные и прогрессивные

ну вот, началось. кого вообще волнует что там считают интересным программисты?

Эриксоны, Фейсбуки, Гуглы и Мозилы выдают нечто вроде Erlang, Rust, Go вовсе не от хорошей эффективности яп с дин. типизацией. :)

а миллиардеры покупают наборы для чистки пупка из платины.

значит — скоро наборы для чистки пупка станут мейнстримом!

пора готовится к празднику. обидно что ваша аргументация была описана мной в постах ранее. меня удручает когда люди действуют по описанному мной сценарию.
на форумах. в жизни — наоборот :)

вот именно!
и? оглянитесь — и прикиньте — а почему он был тогда там, а сейчас — здесь? что было причиной?

Так я ж написал — легко учить + стабильное увеличение популяции нубов (ключевое!), комьюнити, тузлы/фреймворки, поддержка спонсорами.

Сейчас практически у всех топ 15 языков есть большинство аттрибутов: спонсоры, комьюнити, экосистема. Сложность, эффективность и технологические изюмики уже другое дело. Тут и от домена применения зависит и от много еще чего. Пока большинство будут нубами, они всегда будут в топ двигать самое ходовое и легкое в обучении (не путать со скоростью разработки и тем более сопровождения). Это как есть попса, а есть джаз, блюз, рок и классика.

JavaScript и Python они сейчас достаточно всеприменимы во всех областях более-менее.Сугубое ИМХО что их вытеснят рано или поздно узконаправленные вглубь яп — R в machine learning и статистике, какие-нить ФП или ООП с кучей ФП заимствований (Java/C#) в клауде и дистрибьютед и так далее.

оглянуться, а не смотреть вперед, в будущее где «функциональное программирование зохавает весь мир!»

Структурное же захавало, ООП же захавало :) Почему бы и ФП нет :) Не знаю как в других ЯП, но в C# последние года 3-4 только и добавляют фич из ФП. В Java тоже самое. AWS, Azure и другие облака так вообще прямо провоцируют писать в ФП стиле и serverless. Так что я бы не был так категоричен :)

ИМХО что их вытеснят рано или поздно узконаправленные вглубь яп

до сих по узкоспециальное не взлетало. а универсальное — побеждало
выживало так же то что узкоспециальное, в которое втягивалось нечто универсальное.
Что случилось, что теперь сменились «магнитные полюса»?

Я вижу наоборот — требования знания бест практик, жесткие стандарты кода, подходов, чтобы на какой проект ни приди — а там Spring! и так как фаулер великй завещал!
потому что и это — увеличивает скорость разработки за счет — быстроты вхождения в проект, стандартизации учебных материалов и т.п.

в клауде

и пыха нормально крутится. это ж «операционная система» такая Amazon Cloud, Azure Cloud :)

Структурное же захавало, ООП же захавало :)

ну да, что увеличивало скорость разработки — то и захавало
будет логическое программирование увеличивать — зохавает и оно. функциональное увеличит — оно захавает. лингвистическое, — оно. графическое, ...,

Но вы же сами предложили не играться в пророка ;)
я не знаю что зохавает. откуда вы знаете?
какие причины, известные из истории развития ЯП вы используете для прогноза? или — нас ждет «технологическая сингулярность» и потому «вселенная» станет другой, с другими закономерностями

Так что я бы не был так категоричен :)

при этом категоричней меня — уверенно так смотрите в будущее, о котором я не берусь судить, а ковыряюсь в ненужной никому, и особенно пророкам истории и «ее пружинах»...

С Наступающим!
Хороших и новых проектов, которые стремятся сломать ворк лайф баланс и озолотить при этом, чтобы жена не бурчала что живет как в разводе :)

На сучасному С++ пишеться приблизно як на пітоні.

Без втрати ефективності.

Брайан Керниган

Хватит цитатами разговаривать, своих мозгов не хватает?

и кровавое месиво

 Да, если это-что то размером с ls или grep. Во всех остальных случаях кровавое месиво.

ембедед этой бритвой сделан?

По тому и работает как говно если туда не влиты хреналиарды бабок.

нужно учитывать что может прийти null,nil,NaN,object,any

Nah

Я не осилил TypeScript. Поэтому TypeScript говно. Буду и дальше писать лапшу на JS без типов. Что бы хрен кто догадался что вообще происходит в коде.

То есть типы — это единственное что отличает ваш код от лапши?

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

Хреновые программисты обращают систему в комок грязи, а не отсутствие типизации.
На TS тоже можно наворотить такого, что компилятор прохавает, но по факту это никак не привнесёт читабельности или стабильности в проект. Некоторые команды только и занимаются такими играми с компилятором, чтобы он «пропускал билд».
Сравнивать людей, которые умеют в TS со «среднестатистическим джаваскриптером» в корне неверно.

Хреновые программисты обращают систему в комок грязи, а не отсутствие типизации.

тсссс, не раскрывайте секрет, что «индусский код» обычно писан на Java

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

А теперь расскажите мне что типизация этому никак не способствует.

чему — этому?
вот этому:

лучше разбить систему на маленькие изолированные кусочки

не способствует. Богоклассы, с десятком параметров в конструкторе, и еще десятком инжекций — вполне пишутся и с типизацией

выстроить связи между этими кусочками

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

что можно из него получить

можно получить — и будет получено в рантайме — совсем не одно и тоже
если было бы одним и тем же — то и запуск кода не требовался бы

не способствует. Богоклассы, с десятком параметров в конструкторе, и еще десятком инжекций — вполне пишутся и с типизацией

Вполне пишутся и без типизации тоже. Но с типизацией читающий код хотя бы будет понимать что требуется заинжектить.

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

Вполне пишутся и без типизации тоже.

конечно.
но вы ж сказали что типизация — способствует.

Но с типизацией читающий код хотя бы будет понимать что требуется заинжектить.

или читающий доку — где описано что нужно заинжектить
или читающий комментарии в коде, сигнатуры, в которых в названиях параметров написано что нужно заинжектить

цель достигнута — читающий прочитал нечто и понял что нужно?
ее можно достичь — без типизации, или нельзя?

Не использовать типизацию это как не использовать линтер

аха, то есть оказывается линтер может избавить от необходимости использовать типизацию?
и, выше вы написали
читающий код хотя бы будет понимать — а линтер тут при чем?
к процессу понимания кода при чего чтении — читающим?

Зачем делать тупую работу

верно, зачем снабжать типом ListOfPeople аргумент с названием listOfPeople
и типом PeopleRepository аргумент с названием peopleRepository

не делайте этой тупой работы. Я же не делаю :)

или вы, как читающий не понимаете название listOfPeople, но зато поймете название ListOfPeople? оно вам больше даст — понимания кода который вы читаете?

Но с типизацией читающий код хотя бы будет понимать что требуется заинжектить.

Если Вы и так пишете эту информацию почему бы это не сделать в типах?

линтер может избавить от необходимости использовать типизаци

Сами придумали и сами посмеялись. Типизация и линтер инструмент для того что бы сделать код лучше. Если использующий их дурак то и результат соответсвующий.

верно, зачем снабжать типом ListOfPeople аргумент с названием listOfPeople

Вы не поверите но типы можно комбинировать

People[], List<People>
не делайте этой тупой работы. Я же не делаю :)

И как читающий ваш код поймет что нужно передать в listOfPeople? И комментария

listOfPeople - list of people
?
Если Вы и так пишете эту информацию почему бы это не сделать в типах?

потому что я ее уже — написал
зачем мне копипастить эту информацию — еще раз?
мало того, если она не коментом спец формата для линтера
она добавит еще один уровень зависимости.
зачем он мне?

чтобы потом надув от важности щеки рассказывать о — Рефакторинге, который придется проделывать дважды:
изменять код для выполнения
что-то делать с типами, которые не пропускают эти изменения

и в обоих случаях, что с типами, что без — еще и тесты править.

Типизация и линтер инструмент для того что бы сделать код лучше

ну дык неправда же :)
линтер придуман с целью достижения единообразия кода
а типизация — с целью упрощения компилятора

это потом уже, по академическим наработкам в функциональной парадигме придумалось — а может ее и еще для чего-то употребить, типизацию то?

Вы не поверите но типы можно комбинировать

вы не поверите, что я не один год писал и на С, и на Java и на C#
поэтому раз вы меня записали в профаны своим примером

People[], List

то вынужден буду откланятся.

И как читающий ваш код поймет что нужно предать в listOfPeople?

как обычно — откроет исходный код или доку

или его типизация избавит от этого?
от создания объекта типа People?
или получения?

как обычно — откроет исходный код или доку
или его типизация избавит от этого?

Как минимум он щелкнет в IDE на тип и перейдет к его определению, а не будет грепать весь проект.

Как минимум он щелкнет в IDE

NetBeans для PHP использовался мной не один год. Щелкает
VsCode для джс — тоже щелкает

о чем вы говорите? о каком грепе всего проекта?

и как это вы перешли к новому тезису — типы нужны чтобы IDE хорошо подсказывала?

ну ок, тогда так и запишем
типизация придумана с целью быстрой, корректной работы IDE

значит, если она, IDE и так работает удовлетворительно, то незачем тратить время на оптимизацию ее работы

Вы часто приписываете другим слова которых они не говорили.
он щелкнет в IDE на тип

ваши слова?
как преимущества типизации?

а не будет грепать весь проект.

ваши слова?

чем некорректен вывод
значит типизация нужна чтобы не грепать весь проект, и щелкать в IDE по типу?

ну ок, тогда так и запишем
типизация придумана с целью быстрой, корректной работы IDE

Ваши слова. Не мои.

Я писал

он щелкнет в IDE на тип и перейдет к его определению

Если Вы тип не пишите Вы никуда не щелкните и никуда не перейдете. У вас типов нет. Вместо

listOfPeople: List<People>
У вас коментарий
listOfPeople - list of people.
Вы не можете щелкнуть на People и перейти к его определению.
Вам прийдется искать по проекту что же там передается в этот аргумент. И тут окажется что так как типы никто не прописывал то везде передается разное. Иногда даже противоречащее друг другу.
Ваши слова. Не мои.

мой вывод — с ваших слов
в чем он неверен, если вы его арументируете:
чтобы щелакать:

Если Вы тип не пишите Вы никуда не щелкните и никуда не перейдете

а вы не в курсе что IDE работают и по названиям, и частично дерево выполнения строят?

что еще вы мне расскажете, о том что у меня щелкает а что нет?

Вы не можете щелкнуть на People и перейти к его определению.

да ну нах :)
и как же его тогда импортировал, этот Men чтобы создать?

Вам прийдется искать по проекту что же там передается в этот аргумент

в аргумент передается что написано
Если вы собираетесь передать туда listOfPeople наверняка потому что у вас есть этот People. Наверняка вы уже знаете — список чего вы собрались передать.
Если же вы пишите код обработки listOfPeople — то потому что вам у вас задача написать код обработки списка Man и вы наверняка с этого и начали — нашли описание этого Man

Уже второй раз в этой теме про какой-то странный способ написания мне рассказывают — знать не знаю что это, но хочу что-то с этим сделать осмысленное.
и чтобы IDE мне по клику что-то выдавала, а я бац, бац и вставил в код. Знать не знаю что, в IDE накликал, она виновата, мне читать некогда!

И тут окажется что так как типы никто не прописывал то везде передается разное.

Ну, если каждый создаст свой тип
MyMan, FooMan, VasyaMan, ExtendedMan, DBMan, с разным набором полей и реализацей методов — то что вы скажете? Все понятно будет?

Но вот в дин ЯП конечно так и делают, аха. идиёты конечно, кретины. а как же ж, разве может пыхер называться программистом?
а жабоскриптер? а на Clojure — разве могут код писать — Настоящие Программисты?!

Если б я не слышал многократно мнение о тотальной неграмотности и гнать ссаными тряпками из профессии всех этих императивщиков, особенно джавистов от тру функциональщиков, я бы может и обиделся за коллег на дин ЯП :)

а так, «ясно, понятно» — сноб себе орден на грудь поцепил, создал соломенное чучело с другого мнения — и давай примеры приводить :)

Ну, если каждый создаст свой тип
MyMan, FooMan, VasyaMan, ExtendedMan, DBMan, с разным набором полей и реализацей методов — то что вы скажете? Все понятно будет?

TypeScript вас не обязывает так делать. Это вы уже сами наклепали.

Но вот в дин ЯП конечно так и делают, аха. идиёты конечно, кретины. а как же ж, разве может пыхер называться программистом?

В PHP, Ruby, Python добавили статическую типизацию. Вот идиоты.

Но вот в дин ЯП конечно так и делают, аха. идиёты конечно, кретины. а как же ж, разве может пыхер называться программистом?
а жабоскриптер? а на Clojure — разве могут код писать — Настоящие Программисты?!
я бы может и обиделся за коллег на дин ЯП :)

Вы сами это придумали и сами чуть не обиделись)

а так, «ясно, понятно» — сноб себе орден на грудь поцепил, создал соломенное чучело с другого мнения — и давай примеры приводить :

Это как раз вас описывает. Ваши слова:

Тренды в программерской тусовке ничуть не рациональней чем в парижской моде.
написал о пустопорожности надежд что типизация чего-то там существенного позволяет выловить.
это для тех для кого он авторитет — молодежи, которая изучала джс по ютьюбу, и открыла рот от изумления увидев первый в своей жизни ЯП с статической типизацией
TypeScript вас не обязывает так делать.

а вот дин ЯП — обязывает?

В PHP, Ruby, Python добавили статическую типизацию. Вот идиоты.

опционально. разницу понимаете?
что такое возможность ЯП которую можно использовать, а можно не использовать?
И почему чем больше в ЯП — возможностей тем шире область его применения?

Вы сами это придумали и сами чуть не обиделись)

Вы сами рассказываете об каком-то уродском программировании, которое обязано быть на дин ЯП, но от которого якобы избавляет статическая типизация.

Ваши слова:

Мои, да.
И где в них — орден себе?
Мартин не авторитет молодежи? Мне молодежь постоянно его с придыханием цитирует

Трнеды в айтитусовке разве подчиняются рациональным объяснениям=прогнозируемы? обусловлены — правильным академическим и инженерным выбором?
вам только за последний месяц набрать стонов только с доу о победе «пластмассового мира», жабоскриптерах и т.п.?
или привести историю плевания в Джаву всего правильного программиского мира? ну тогда, когда она появилась?
или джс — сделанный за 10 дней? а может Python Гвидо задумывал как промышленный ЯП?

О надеждах — то есть вы будете оспаривать утверждение что серебряной пули — не существует?

опционально. разницу понимаете?

В TypeScript типизация тоже опциональная. Я вам уже писал

Вы TypeScript вообще смотрели? Может прежде чем критиковать что то было бы неплохо с ним познакомится?

Вы же пишите

Вы сами рассказываете об каком-то уродском программировании, которое обязано быть на дин ЯП, но от которого якобы избавляет статическая типизация.
Мои, да.
И где в них — орден себе?

Вы и другие троли пришли в топик «TypeScript — это не только про аннотацию типов. Примеры из практики» и рассказываете что TS не нужен. Это как раз

сноб себе орден на грудь поцепил, создал соломенное чучело с другого мнения

TS нужен. Это вы не нужны в этом топике.

TS нужен. Это вы не нужны в этом топике.

если вы модератор — то забаньте
а если нет — то не вам указывать кто где нужен на публичном ресурсе.
в тряпочку помалкивайте, малограмотный вы мой

плагинчик для бана у меня в профиле. вас туда и помещаю, там немного таких, гордитесь — попали в мой топчик!

Да я согласен с тем что правильно прописанные типы будут помогать в разработке!
С этим глупо спорить.

Вопрос в том, что в практике люди видят в этом какую-то серебрянную пулю, которая превратит

комок грязи

в прекрасного белого лебедя. А по факту — тестов нет, документации нет никакой, а типизация применяется для типизации. В этом случае имхо она никак не поможет проекту, ну разве что каким-то новичкам позволит не совершать совсем уж диких ошибок.

Ещё раз, хорошо сделанные типы — ок, но это не достаточное условие для того чтобы вытащить проект.
Их отсутствие — не критично (неприятно, но не критично), если есть тесты и дока.

А по факту — тестов нет, документации нет никакой, а типизация применяется для типизации.

Даже так лучше чем «тестов нет, документации нет никакой, типизации нет».

Как минимум в хорошо типизированном проекте намного проще проводить рефакторинг, а это уже большая помощь для того что бы «прекрасный белый лебедь» не превратился в «комок грязи» в будущем.

Человек который не использует TypeScript все равно думает о типах. Что должна принимать функция которою я хочу написать? Что должна возвращать? Почему бы не закрепить эту информацию в коде, а не в комментариях (если их пишут в этом проекте, очень частно не пишут)? Что бы она не потерялась и что бы компилятор помогал находить ошибки.

Даже так лучше чем «тестов нет, документации нет никакой, типизации нет».

то есть вы утверждаете, что причиной того что тестов нет и документации нет — отсутствие типизации?

Как минимум в хорошо типизированном проекте намного проще проводить рефакторинг

причина которого вызвана — устаревшей, ставшей неадекватной — типизацией :)

Человек который не использует TypeScript все равно думает о типах

не думает. он думает о свойствах конкретного объекта, а не его типе

он думает — о выводе name например, а не о том что это name у типа Товар, или типа Man

этот аргумент, «все равно думает о типах» для меня сродни аргументу верующих
а атеисты тоже верующие, только не в Бога, а в «отсутствие Бога»!

что бы компилятор помогал находить ошибки.

какие именно ошибки? какой именно класс ошибок позволяет находить статический анализ типов?
вот в чем вопрос.
и почему тесты — не могут отловить этот класс ошибок, если они есть, тесты?

Почему бы не закрепить эту информацию в коде,

потому что любое внесение информации в компьютер человеком — требует времени
любое добавление в код, которое ограничивает последующие внесения изменения в код — увеличивает затраты — времени

Время — вот чем ограничен любой разработчик.

В идеале, конечно, надо бы не только типы внести в код. а все отрывки из тех задания и спецификаций, а также решения принятые на митингах — относящиеся к этому коду, повлиявшие на него. А также автор кода, хорошо бы, пусть бы привел свои рассуждения, и аргументацию, почему он выбрал такое решение, а не другое. ведь можно было и другое написать.
Сколько это будет требовать — времени?

то есть вы утверждаете, что причиной того что тестов нет и документации нет — отсутствие типизации?

Это Вы такое утверждаете.

и почему тесты — не могут отловить этот класс ошибок, если они есть, тесты?

Вы часто приписываете другим слова которых они не говорили. Может выявить. Только Вы вместо написания типа пишете лишний тест которого бы не было если бы Вы написали тип.

он думает о свойствах конкретного объекта, а не его типе
он думает — о выводе name например, а не о том что это name у типа Товар, или типа Man

Это называется структурная типизация. Вы TypeScript вообще смотрели? Может прежде чем критиковать что то было бы неплохо с ним познакомится? Вероятно ваши рассуждения о типах строятся на Java или чем-то подобном. В TypeScript система типов намного мощнее и удобнее.

function lysakPrint(obj: { name: string }) {
   console.log(obj.name);
}
Уже по сигнатуре функции Вы видите что `lysakPrint` работает с любыми объектами у которых есть name.
Вы часто приписываете другим слова которых они не говорили

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

Это называется структурная типизация.

я в курсе что в TS структурная типизация.
если вы дальше будете дискутировать с кретином в моем лице — то извините, об этом я давно говорю
Если кто-то кого из дискутирующих считает кретином — то один из них точно кретин. Не исключено что и оба.

Уже по сигнатуре функции Вы видите что `lysakPrint` работает с любыми объектами у которых есть name.

и откуда видно из сигнатуры что будет печаться name? и, мне бы иницалами заменить имя отчество. в сигнатуре это видно?
а в типе?
или надо
открывать доку
если нет — читать комменты
если нет — смотреть код

что вы видно в 

function lysakPrint(obj: { name: string })?
а что видно в
lysakPrint(objWithName)
lysakPrint(man) // уже меньше, 
/**
{Object} man with propery name
*/
lysakPrint(man)
то есть, соломенное чучело это когда приводятся какие-то нелепые, выхолощенные примеры, как будто чел вообще никогда не программировал, а когда оказалось что знать надо гораздо больше тех пары строк что он видит на экране, чтобы написать свои — взвывает, «а я думал программирование это просто... сделайте мне чтобы было просто, а?»

иди кукарекай в другой двор

Достойная аргументация. Ни добавить, ни убавить.

плагинчик для бана у меня в профиле. вас туда и помещаю, там немного таких, гордитесь — попали в мой топчик!

Что ему еще ответить?

Пишет

то есть, соломенное чучело это когда приводятся какие-то нелепые, выхолощенные примеры, как будто чел вообще никогда не программировал

При этом сам первый приводит абсолютно идиотские примеры

верно, зачем снабжать типом ListOfPeople аргумент с названием listOfPeople
и типом PeopleRepository аргумент с названием peopleRepository

Ну камон, можно же техничней огрызнуться. Более утонченно.

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

...а я так и не понял — почему для статической проверки типов не взлетел ненавязчивый Flow
Тренды в программерской тусовке ничуть не рациональней чем в парижской моде...

Как по мне, для любого ЯП с дин типизацией возможности статического анализа типов должны такими и быть — аннотациями, или вкраплениями, которые ни к чему не принуждают, а могут использоваться по желанию, и в той степени в какой нужно для конкретных проектов и команды.

// @flow
function square(n: number): number {
  return n * n;
}

В php даже управление мягким/строгим приведением типов можно управлять — на уровне файла исходного кода

<?php
declare(strict_types = 1);
function getString(string $str) {
 var_dump($str);
}
$int = 12;
getString($int);
//Fatal error: Uncaught TypeError: Argument 1 passed to getString() must be of the type string, integer given...
и указывать типы где надо, а где не надо — то и не указывать

И в Питоне есть подобная штука typing — Support for type hints
Когда же говорят что TS это «всего лишь» надмножество JS, ай, оставьте

Что это за JS такой:

type DtoValidator<T> = {
  [key in keyof T]: (v: unknown) => v is T[key];
};
а такого, раз уже взялся TS для написания кода — будет много
Тренды в программерской тусовке ничуть не рациональней чем в парижской моде

Чем красивее лендинг страница очередной либы, тем больше шансов у нее взлететь)

...а я так и не понял — почему для статической проверки типов не взлетел ненавязчивый Flow

насколько помню тот период:
1. коммьюнити Flow не особо росло(я ориентируюсь на вопросы на StackOverflow — подписался на фильтр и видел, что новых вопросов совсем мало)
2. Microsoft ж, а Fb не особо продвигал флоу
3. Angular2 с TypeScript

та это понятно что набор случайностей, «авторитетов»
но когда надо — то и на Hack народ стал смотреть
Был даже перевод википедии на Hack (или планы...)

Но вышла 7ая пыха, с значительно улучшенным быстродействием, и все улучшающимся тайп-хинтингом (кому надо), о Hack и забыли вне FB

Angular2 с TypeScript

он не только с TypeScript. Он весь калька с энтерпрайзных бест практик по созданию монолитов на джаве/дотнете.
Это его главная киллер фича — бекендеру с джавы/дотнета все там знакомо и привычно. Когда его в фулстек толкают :)

...а я так и не понял — почему для статической проверки типов не взлетел ненавязчивый Flow

Потому что...
Going forward, Flow is staying open source and we will be happy to review pull requests that improve library definitions and website documentation, but we may not be able to accept PRs for Flow itself if the PRs don’t align with our priorities. The complexity of Flow’s codebase makes it difficult to contribute to Flow itself, and our company-internal build systems, performance tests and integration tests make it very time consuming to review and integrate such pull requests, so we may close PRs that don’t align with our priorities. Similarly, we will close GitHub issues when we know we will not be able to provide timely support.

Иными словами, мейнтейнеры flow открыто говорят — „мы сделали этот инструмент для наших собственных нужд внутри фейсбука. И развивать этот инструмент мы будем согласно нашим потребностям, а не хотелкам коммьюнити. Ваши пулл-реквесты мы принимать не будем.”
medium.com/...​e-engagement-e721a4eb4d8b

а-а-а, тогда да, понятно почему. спасибо за исчерпывающую и точную инфу

Так тайпскрипт уже давно умеет в аннотации в стиле jsdoc. В некоторых проектах мне даже приходилось так аннотировать js-код — бо́льшая часть возможностей языка таким способом вполне реализуется. Причем, можно такой аннотированный js статически проверять тайпскриптом.

Ну да, умеет. Так зачем же на нем сам код писать тогда? ;)

В этом же вопрос. А так как я писал на нескольких ЯП с стат типизацией, то знаю что она позволяет отловить, и какую цену приходится платить.
Но там эта цена была оправдана, потому что главная цель её была — генерация транслятором эффективного машиного кода, а не отлов опечаток.
Случайно в другой теме уже написал о пустопорожности надежд что типизация чего-то там существенного позволяет выловить.

Жизнь покажет. Мне же лично интереснее попробовать ReasonML, чем вариант C#.

попробовать ReasonML

Пробовал его чисто для фана, вещь интересная, и реализация типизации там крутая. Но как то подзатих он в последнее время, врядли выстрелит.

вот и я для фана хочу. на вид — интересная штука
вообще, мое сугубо субъективное мнение, ощущение — OCaml куда более человечный ФЯ чем Haskell

почему для статической проверки типов не взлетел ненавязчивый Flow

Потому что Facebook до сих пор не сподобились заставить его нормально работать под Windows. У нас фронтенд одной внутренней системы написан на Flow, и работать с ним под Windows — это боль. Выручает только возможность VS Code поднимать свою серверную часть в WSL2, где Flow работает как положено.

Ну и в современном TypeScript система типов помощнее, всё же, будет, и вывод типов в нём работает намного прямее, чем во Flow.

Пишу как человек, использующий и то, и другое в повседневной работе.

Фанаты TS часто забывают, что в большинстве баги типизации, что ловит ts, быстро находятся и без него. А меташума в коде добавляется много)

что в большинстве баги типизации, что ловит ts, быстро находятся и без него

от, мне очень интересно, как это в принципе возможно замерить. Мы ж не в vi код пишем, так? Так что подсказки к параметрам или же ошибки несоответствия типов получаем буквально сразу.
А ошибки — которые «находятся» — это как минимум что-то рантаймное или вообще логическое, что и не ожидаем отловить статической типизацией.

Как посчитать первое, чтоб сравнить со вторым? Или речь о «внутреннем ощущении»?

Так что подсказки к параметрам

современные IDE неплохо выдают и для дин ЯП. Но, хуже конечно чем для стат ЯП.

ошибки несоответствия типов получаем буквально сразу

ессно, раз стат типизация — то она будет ругаться на передачу чего-то с полем id, потому что тип не тот. и ее не интресует что внутри мы только к этому полю и обращаемся, а поэтому — любое нечто имеющее поле id годится. Надо будет убалтывать. Плодить код, примерно как в Go до появления дженериков. Или — наворачивать описание типа, или выделять интерфейс, и т.п.

Или речь о «внутреннем ощущении»?

Конечно. Оно же и об

ошибки несоответствия типов

только — внутренние ощущения.

это ж пример
парадокса Блаба (это условное название гипотетического языка программирования средней сложности):
некто, отдающий предпочтение одному конкретному языку программирования, будет знать, что он более мощен, чем другие, но не будет знать, что он менее мощен, чем все остальные. Причина в следующем: чтобы создать программу на определённом языке, надо думать на этом языке. Отсюда и вытекает парадокс: типичные программисты «удовлетворены любым языком, которым им пришлось пользоваться, потому что тот диктует им, как они должны думать о программах»
Другими словами — конечно, если я пишу на Джава и могу всюду работать с Object, я не буду этого делать, а буду указывать тип ожидаемого объекта

А давайте понаблюдаем за собой — когда пишем код. КАК появляется такая ошибка? Почему ты пихаешь нечто туда, где будет вызван метод, которого нет, у того что ты туда пихаешь? Что у тебя было в голове, какая цель — передать «Вася» и «Петя» в randomMinMax(min, max), вместо Вася .weight и Петя.weight?
И почему ты, если уж так надо, не создал для этого randomByWeight?

Но, это ж рефлексировать нужно. Думать.
О том что ругань на несоответствие типа вызвана чаще — ее, системы типов, примитивностью, чем тем что мы хотим сделать что-то действительно нелепое с точки зрения логики алгоритма, программы: сравнить «соленое» и «красное» например.
При этом, системе типов придется объяснять что это — одно и тоже в данном случае, потому что в данном контексте нам просто нужно проверить «оканчивается» ли это нечто на «ое».

Далее, думать о том что
Почему другой программист передал нечто, у которого ожидается метод foo100500?
То есть почему так вышло что о SOLID разговоров много — но у объектища десятки методов, при этом он из семейства объектов у некоторых из которого есть такой метод, а у некоторых нет. И ессно, при такой «правильной архитектуре» упомнить что в данном контексте нам нужен только объект с foo100500 сложно

А как посчитать время которое экономится на такое?
Когда мы — знаем контекст использования, у нас есть цель этого контекста, и мы — не тратим время сейчас на описание этого контекста, и не тратим потом на изменение этого описания контекста, потому что появился — еще контекст

То есть, чтобы посчитать такое, надо представить, что мы хотим сделать нечто, сознательно хотим, а не опечатались, и это — корректно, логично, но компилятор нас обругает потому что «тип не тот», и сколько нам нужно времени чтобы заткнуть ему рот, и сделать таки то что мы хотим

А давайте понаблюдаем за собой — когда пишем код. КАК появляется такая ошибка?

та нанаблюдался уже. При переключении между проектами(т.е. сброс контекста, «так привык» уже не помогает) трачу дофига времени, когда вместо того, чтоб «просто вызывать» метод — лезу смотреть, как он устроен внутри. Бо параметр-коллбек может вызываться синхронно или асинхронно, deleteSomething(something) может ожидать тупо id(да да, проблемы именования), может объект со свойством id, а может и кучу других пропертей ждать — например, шоб вывести «красивый еррор месадж» в случае ошибки, задействуя другие проперти. А мне надо «просто удалить связанную сущность», и разница между «передать только айди» и «вытянуть из редакса полный объект и передать его» несущественна. Но надо понять, какие свойства тут ожидаются.

Ошибка? Нету её. Но и когнитивная нагрузка растет, вникание в методы, которые вызываю, занимает время, сопоставимое с написанием самой бизнес логики.

И ессно, при такой «правильной архитектуре» упомнить что в данном контексте нам нужен только объект с foo100500 сложно

Интерфейсы ж, не?

когда вместо того, чтоб «просто вызывать» метод — лезу смотреть, как он устроен внутри.

я и на джаве постоянно лез.
код потому что у нас — самодокументируемый, а поэтому ни доки, ни комментов к нему нет.
а те что есть — IDE сгенерила, скопировав название типа и параметра из сигнатуры.

При переключении между проектами(

согласен. тут — проблема общая
особенно остро такая у фулстека стоит, когда прыгать между беком и фронтом надо

Но надо понять, какие свойства тут ожидаются.

на Джаве — так же. я не помню чтобы типизация избавляла меня от этого — надо понять

шоб вывести «красивый еррор месадж» в случае ошибки

для этого — фреймворк нужен. с слоями абстракций, фабриками форматеров, и т.д.
так просто — нельзя в 21ом веке, засмеют.

Но и когнитивная нагрузка растет, вникание в методы, которые вызываю, занимает время, сопоставимое с написанием самой бизнес логики.

ессно.
программист это преимущественно — читатель а не писатель
писать код — плевое дело
упоминал уже, еще скажу — дети так быстро тягают блоки в Scratch — ух
а вот когда оно работает, но не так, то ой — смотрят, смотрят на то что натягали, и — «не знаю почему не работает»

а уж чужой код...
читать и думать. думать и перечитывать.

а писать то да, плевое дело. любой сможет
прочитать — вот где сложность.

Интерфейсы ж, не?

ну да. если ЯП требует — придется плодить и множить интерфейсы :)
а если не требует — то и не придется

в том же и фокус покус
когда у вас в руках молоток — вам придется вбивать шурупы а не вкручивать :)
а когда отвертка для гвоздей — то тоже, глядите ручку не разбейте

ЯП — навязывает способы решения. Явно или неявно подталкивает к выбору одних, и отказу от других. и когда подчиняешься этому диктату — да нет проблем особых, на любом ЯП

Бо параметр-коллбек может вызываться синхронно или асинхронно

Как бы на этот счет давно есть соглашение- если это коллбек node-стайла (err, ...data) то он всегда вызывается асинхронно, если коллбек другой сигнатуры, то он должен быть синхронный. Можно еще подкрепить очевидное, дав ему имя параметра отличное от callback — handler/reducer/etc.
Да и с промисами юзание коллбеков уменьшилось на порядок, IDE сама успешно выкидывает хинты, когда асинхронную функцию вызывают как синхронную, без единого лишнего символа аннотаций.

deleteSomething(something) может ожидать тупо id(да да, проблемы именования), может объект со свойством id,

Если есть проблемы с именованиями, то проблем с описанием и именованием типов не будет? :)
Вряд ли кто будет ждать в deleteById объект с одним полем id. Но если и будет, то IDE при
написании вызова delete({id}) все ровно подсказывает сигнатуру параметров и там будет аргумент {id}- вполне понятно что это объект, что в нем есть и это абсолютно «бесплатно».
А так исчерпывающих вариантов масса
delete(obj)/deleteById(id)/deleteBy(pattern|schema)
Если сильно надо- jsdoc’ом усилить.
Увы в TS очень сильно перегнули палку с диктатурой, а более мягкого инструмента посередине между jsdoc и TS по сути нет, если d.ts не считать. Мягких опциональных аннотаций типов было бы достаточно- тот же jsdoc, но в инлайн семантике.

Можно еще подкрепить очевидное, дав ему имя параметра отличное от callback — handler/reducer/etc.

и мы так реализуем типизацию, но через договоренности об именах. Так же как «приватные поля начинаем с _». Не то, чтоб плохо, но хрупко.

Если есть проблемы с именованиями, то проблем с описанием и именованием типов не будет? :)

Могут быть, могут не быть. Не серебрянная пуля, но при реюзе типов вообще проблем не будет(ну, в смысле, deleteUser(user: TUser): void, а сам TUser описан давно и используется в куче мест). Опять же, есть implicit type, просто через объявление дефолтного значения — если параметр примитив, например, строка.

Опять же, нормальное название давать всё равно стоит. Не то, чтоб одно другое заменит.

тот же jsdoc, но в инлайн семантике.

я как-то пробовал документировать через JSDocs параметры-коллбеки(сложный модуль, не во всем проекте). Это больно. Что Flow, что TS в этом смысле далеко впереди.

Увы в TS очень сильно перегнули палку с диктатурой

А можно подробнее? О чем речь? Ну, с учетом что есть выведение типов

Не то, чтоб плохо, но хрупко.

Каким образом это хрупко? В принципе, линтер/IDE может считать все поля с _ приватными и показывать хинт, т.е это вопрос возможности линтеров, без всяких там километровых модификаторов как у джавы. Если IDE кажется, что кодер хочет выстрелить себе в ногу, то ее удел просто узнать уверен ли он в этом, а не пытаться запрещать.

но при реюзе типов вообще проблем не будет
а сам TUser описан давно и используется в куче мест

Так так и jsdoc- только кто бы кто описывал правильно его структуру :)

я как-то пробовал документировать через JSDocs параметры-коллбеки

Как бы ничего больного там нет, но буков многовато, хоть они и автоматом IDE подставляются на 80%. JsDoc это ж не только типы, а и потенциально доки с примерами, ссылками и т.д.

А можно подробнее? О чем речь?

Ну TS это не JS, а хотелось бы инструмент сугубо как линтер (по сути Flow), с базовыми возможностями типизации, которые опциональны- никаких там упоротых any, которые тебя заставляют везде расставлять, хотя тип тебе сейчас не нужен, а может типизация это куска тебе вообще нафик не надо. Может меня типы в паре мест только интересуют, может только для публичных экспортируемых интерфейсов, но нет, за меня решили, что тут у нас типизированная джава, и все должно быть описано «от» и «до» с бюрократическим подходом. Если что не так с типами, даже если сам код рабочий, то хрен соберешь проект без костылей.
В идеале еще чтобы IDE могла скрывать по хоткею все типы в коде, чтобы в глазах от них не рябило, особенно от километровых дженериков при чтении логики.

Ну, с учетом что есть выведение типов

Это +/- работает и в обычном js коде. Собственно, примерно так это и должно работать- IDE должна пытаться подсказать по контексту, а юзер по желанию мог бы более явно указать типы, если ему надо однозначность в данном месте или на данном этапе коддинга.
С расширением ECMA семантики (классы, приватные поля, асинхронные функции, ...) адекватно предсказывать все легче. Да и jsodoc пользоваться стало проще, ибо половина модификаторов для имитации структуры класса стала по сути ненужной в 99% кода.
Имхо, для экосистемы JS была бы куда естественнее типизация+валидация, построенная на декораторах, которые бы ассертили входные данные в рантайм и при этом линтер мог их понимать и при статическом анализе. Как бы незачем это все размазывать по кучи инструментов. В продакш сборке бы автоматом вырезать все не влияющие на логику ассерты, пробежав по AST и профит. Рантайм уж наверняка отловит все, а в статике базовое.
Что то вроде (хотя декоратора для инициализатора переменной в ECMA пока нет):

@fn(User, string.email)
const changeUserEmail= (user, email)=>{}
Тут бы и IDE понимала, что email имеет тип string, и рантайм бы проверил что это строка формата емейла. И все довольны.
Ну и нечто вроде этого для полей
class Cat {
  @string
  name = "";
  @type(string | number)
  foo = 123;
  @array
  bar = [];
}
Но с такой сыроватой спецификацией декораторов в ECMA, вряд ли кто то будет там копать в эту сторону.
потому что тип не тот. и ее не интресует что внутри мы только к этому полю и обращаемся, а поэтому — любое нечто имеющее поле id годится.

структурная типизация, которая в том числе есть в TS не подходит? это по сути же отражение вашего требования «чтобы была такая-то пропертя в обьекте»

и ее не интресует что внутри мы только к этому полю и обращаемся,

это плохо, если для использования кода надо лезть внутрь и считать — «но она же только в id заденет в этом кейсе вызова». Если это не только один кейс вызова, значит в интфрейсе изначально надо было ставить просто id. Такое лазание по кейсам внутри потом приведет к тому, что чтобы сделать какой-то инкремент функционала — надо всю систему вспоминать как работает, вся имплеметация всего, и все это дело в голову погружать вместо того, чтобы при работе с кодом прогружать в голову только текущий «скоуп», а на все остальные иметь явный контракт + тесты, которые считаются как гарантия того, что эти используемые обьекты выполняют свою работу как ожидается и по сути является сжатой информацией о здоровенном куске функционала.

Почему ты пихаешь нечто туда, где будет вызван метод, которого нет, у того что ты туда пихаешь?

числа легкий кейс, что если это обьект с данными? как понять например что передать тут drawFigure(figure)? или тут createValidator(schema)? лазить внутри по циклам в имплементации/примерах_вызова_по_всему_коду или все же сконструировать обьект типа Schema со всеми нужными ему констреинтами? бывало замечал, играя с некоторыми библиотеками, что это временами скатывается в примеро-ориентированное программирование, в документации схемы данных нужной для работы функционала нет, зато есть классные примерчики, жаль что не покрывает всех возможных вариантов использования.., может я что-то не так делал?

То есть, чтобы посчитать такое, надо представить, что мы хотим сделать нечто, сознательно хотим, а не опечатались, и это — корректно, логично, но компилятор нас обругает потому что «тип не тот», и сколько нам нужно времени чтобы заткнуть ему рот, и сделать таки то что мы хотим

Функция должна требовать как можно меньше данных нужных для ее работы (убирая лишнее или используя параметрический полиморфизм или полиморфизм подтипов), если в ее контракте указано, что надо такого рода данные, значит их и надо передавать, если они все же слишком сложные, значит разделение отвественности было скорее всего неправильным и это уже особенность не типов, а больше поведения, типы всего лишь констатируют ситуевину. Если модель может иметь опциональные данные, значит они должны таким образом и конструироваться, если надо

структурная типизация, которая в том числе есть в TS не подходит?

1. логика работы справляется с отстутствующим проперти. обязана :)
2. если оно обязано быть и заполнено — то это ответственность в месте создания объекта
3. я нередко добавляю проперти по необходимости, во время выполнения, и об этом известно только в паре мест, остальным знать необязательно. и типы меня не бьют по рукам за это, и не требуется рефакторить чтобы доказать компилятору что я знаю чего хочу, и понимаю все риски прокидывания данных между несколькими местами, не обращаясь напрямую, и не уведомляя об этом посредников, слои, через которые пройдет этот объект. (отдельная большая тема, как правильно использовать возможности что предоставляются дин ЯП)

и того — что и зачем собственно проверяем типом если оно — и так будет работать?

это плохо, если для использования кода надо лезть внутрь

зачем туда лезть, если ты знаешь что ты хочешь, и отдаешь объект куда надо?
а если ты не уверен что то куда передаешь сделает то что ты хочешь
то чем тип поможет? тебе все равно надо залезть внуть и убедится лично — да, оно сделает то что нужно.

чтобы при работе с кодом прогружать в голову только текущий «скоуп»

если не знать домен, не читать не слышать дев гайды по архитектуре проекта, то да будет тот самый «индусский код»: бойлерплейтный, с кучей интерфейсов и классов созданных чисто для текущего скоупа
и это еще так сяк
скорее всего еще будет оверинжиниринг
«- Навіщо тобі це?
— А щоб було!»
когда ты не знаешь домена :)

а на все остальные иметь явный контракт + тесты,

если бы на «джаве» не нужно было писать тесты, если бы в названия переменных да и классов — не пихались названия типа — то да, вот она реальнейшая польза
но — и тесты пишутся, причем — юнит! для статического типизированного языка!!

которые считаются как гарантия того

но гарантий почему-то нет в итоге
отладка статически типизированного кода ничем особо не легче чем динамического. И так же неделю можно просидеть в поиске причин бага, и еще неделю в фиксе
по моему опыту

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

как понять например что передать тут drawFigure(figure)?

зависит от того — что такое draw и figure в домене. это надо понимать — домен.

createValidator(schema)?

понятия не имею какими бы типами не было снабжено
для этого надо знать — домен

лазить внутри по циклам в имплементации/примерах_вызова_по_всему_коду

если по коду на Джаве мне приходилось лезть, даже заглядывать в исходники звездных библиотек...
где обещанный профит?

или, вот недавно про ормы вспомнилось — да постоянно в кишки надо заглядывать, что оно и почему??? генерит такой sql код
ну и, чем типы помогают? почему не избавляют от потребности изучения — реализации?

это временами скатывается в примеро-ориентированное программирование, в документации схемы данных нужной для работы функционала нет

ну да, все так.
я например документацию читаю только вначале. а чем больше работаю с чем-то, тем чаще пользуюсь исходным кодом как документацией. потому что он источник правды, а не документация. конечно бывает очень хорошая документация, что ее почти хватает. очень нравилась майкрософстовская, когда на C# писал.

Но в общем — в исходный код смотри, если что-то не понятно.

все же сконструировать обьект типа Schema

ну дык тоже самое: или fooSchema = createShema(opts) или fooSchema = new Shema(opts)
и кругом:

funcFoo(shema) {...}
{shema: mySchema, ...}

ты не знаешь что такое shema?
а если не знаешь, то чем тебе поможет объявление типа?
а если схем несколько, скажем какая-то для БД, какая-то для отрисовки грида, то два вопроса
— почему бы и не назвать shemaDB, shemaGrid
— и как так получается что в одном месте они — встречаются, если по идее они должны использоваться весьма в отдаленных друг от друга местах

Функция должна требовать как можно меньше данных нужных для ее работы

а при чем тут это требование к декомпозиции к — статической типизации?

если в ее контракте указано, что надо такого рода данные

внятные названия переменных, аргументов и функций и есть такой контракт.
просто — не проверяемый компилятором, а потому — не обязательный
и потому в fooSchema кто угодно может добавить что угодно
и это может быть — выстрелом себе в ногу, а может — избавлением от борьбы с типами в узкоспециальном сценарии
Самодисциплина нужна, и ответственность для хороших программ на дин яп :) У код ревьювера так точно, если в команде много джунов

Про контракты — сигнатура функции это пародия на контрактное программирование. Если интересно узнать каким оно должно быть, чтобы иметь «гарантии от контрактов» см в Eiffel от Мейера и его Object-Oriented Software Construction
Вот там — контракты.

разделение отвественности было скорее всего неправильным и это уже особенность не типов, а больше поведения, типы всего лишь констатируют ситуевину

типы вообще ничего не констатируют, в общем случае (разве что в настоящих функциональных языках программирования)
Типы в мейнстрим языках — это просто бирочки, ярлычки, аннотации, «комменты»
Примитивные типы — да, в языках с честной компиляцией в нативный код — полезны. Не человеку, — компилятору
Поэтому и когда мешают, та

void * ptr 
foofunc (void *bar)
и пошел ваять:)

Но есть же все таки плюсы у статической типизации?
Конечно
Из исследований что встречал преимущества проявляются все отчетливее с ростом размера кодовой базы и количества программистов что над ней работало. а уж если программисты после вайти курсов, то очень полезно их, программистов типами привести в норму :)
и, как выше упомянул, если ты в аутсорсе, у тебя семь пятниц проектов на неделе, с разных доменов, то конечно — знать домен не получится, а значит — да фигачь тупо как типами прописано. тестировщики проверят!

Но если мы идем в микросервисы, то вот честно, я так и не понял зачем зачем Go типизированный :) ну, разве что ради компилятора, как и С

логика работы справляется с отстутствующим проперти. обязана :)
2. если оно обязано быть и заполнено — то это ответственность в месте создания объекта
3. я нередко добавляю проперти по необходимости, во время выполнения, и об этом известно только в паре мест, остальным знать необязательно

значит у вас и id колонка не обязательна, например вы передаете изменчивой структуры обьект, а та функция обрабатывает ее условно как контент, значит передаваемый обьект должен иметь более стертый тип(о чем я писал в пункте про минимально необходимую информацию), например какой-нибудь map. В данном случае пытаясь понять пример что вам надо я уже в голове прогнал 2 отдельных кейса — когда функции надо обязательно колонка id, условно какой-то entity и когда параметр это динамической струтктуры обьекта, а ведь это 2 разных ситуации, первая функция завалится если вы будете в каких-то случаях кидать, а в каких-то нет, особенно например весело если это на проде :) Какой бы вы не делали динамический по структуре обьект, он все равно обрабатывается статическим по своей природе кодом — определенными конструкциями, это может быть проход по ключам и прочее — в любом случае эта завязанность на тип обьекта создается, хоть и неявно, просто в случае с типами она констатируется, в ином случае мы либо держим в голове кеш про все параметры проекта либо же ходим каждый раз в код — хотя инфа-то вот она, в типе: «можно передать обьект с любым набором ключей», «можно передать обьект, но обязательно с id»

зачем туда лезть, если ты знаешь что ты хочешь, и отдаешь объект куда надо?

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

то чем тип поможет? тебе все равно надо залезть внуть и убедится лично — да, оно сделает то что нужно

если функция декларирует какой-то тип, но все равно валится, значит она не описала, что ей надо нормально. А тут уже два варианта, либо писатель просто обьявляет какие-то контейнеры для данных, строки, указатели, вместо того, чтобы ограничить статически способ конструирования обьекта, либо в данном языке типы имеют недостаточные возможности для указания необходимых условий, например условие not null . К первому случаю могу лишь сказать, что типизация тоже требует понимания что ты делаешь, а не как вы выше описали — «вошел ввайти с курсов», например можно написать createValidator(schema: any) или createValidator(schema: {definition: string[]}), но ведь на самом деле createValidator не с любой структурой данных работает или это не просто массив строк, а там должны быть только конкретные указания. К второму случаю — с такими моментами приходиться мириться в языке, но все равно же даже в таком случае отметается большое количество невалидных вариантов.

если не знать домен, не читать не слышать дев гайды по архитектуре проекта, то да будет тот самый «индусский код»: бойлерплейтный, с кучей интерфейсов и классов созданных чисто для текущего скоупа

а я и не отрицаю необходимость понимать домен, но не надо приравнивать знание домена и колупание во всей кодовой базе (а я в том сообщении явно указал слово «имплементацию») чтобы понять что это будет работоспособно. Именно такая необходимость и приводит к тому, что «дебажим неделями», потому что какой-то код пишется таким образом, что завязан на то, что там где-то в другой части проекта в такой-то конструкции этот кейс заходит. Вместо того, чтобы зная отвественность выраженную в контракте понять — это использующий код передал не по контракту (частный случай — несовместимый тип) или используемый код неверно имплементирован для валидного ипута данных.

скорее всего еще будет оверинжиниринг

я тоже не поклонник такого, но при чем тут типы? Это же деталь поведения, можно таким же образом в безтиповом коде написать тучу фабрик, мапперов данных, билдеров для билдеров и прочего. Я бы сказал, что это больше изначальный майндсет, такой человек и в js такое же напишет, но при этом будет ругаться, что ему типы не подсказываются.

но гарантий почему-то нет в итоге

А вот это плохо, значит тот кто использует типы не до конца понимает, что ними можно фиксировать в том числе и гарантии, а не просто как контейнер для данных «лишь бы прокинуть».

зависит от того — что такое draw и figure в домене. это надо понимать — домен.

вот тут интересно, что например именно надо знать, по вашему мнению? я вот например понимаю, что figure это набор вершин и ребер условно говоря, этого хватит чтобы работать с функцией? а сколько у них координат, есть ли Z, есть ли метаданные, а как они названы в структуре данных (не нашел в воображаемом коде, там в каком-то цикле читается обьект), а можно ли там только ребра передать? или только вершины? координата int/double?

понятия не имею какими бы типами не было снабжено

var idSchema = new LiteralSchema(Constraint.MinLength(1), Constraint.AllowedSymbols(char.IsAlphaNumeric))
new ObjectSchema(new RequiredField("id", idSchema), new AtLeastOneField("type", new OneOfSchema("completed«, «paused»), «metadata», Schema.Any))
снабжено типами, имею понятие что делать, не валится в специфичных условиях и не надо дебажить по всему проекту.

а при чем тут это требование к декомпозиции к — статической типизации?

потому что в типизации мы явно отображаем как мы декомпозировали обьекты, если мы хотели на самом деле по другому декомпозировать (иметь более стертый тип), но написали какой-то более конкретный и ломаем голову как это обойти, то виновата ли тут типизация?

внятные названия переменных, аргументов и функций и есть такой контракт.

безусловно это важно, но как например createValidator(schema) можно улучшить, чтобы этого хватало?

ну и, чем типы помогают? почему не избавляют от потребности изучения — реализации?

в моем примере с валидатором они нам помогли передать то, что нам надо без целого поля проблем с тем как взамодействовать с обьектом, если у меня вопросы к имплементации, она имеет недостаточный перформанс итд — я работаю с ней отдельно исходя из знаний того, что она должна обрабатывать и что возвращать, чтобы не поламать другой функцонал. В примере с орм они вам гарантировали, что вы получите ожидаемый результат, но вопрос перформанса все же остается на клиенте бибилотеки, я бы сказал по большей мере из-за того, что такая бибилиотека пытается дать достаточно много контроля над тем, что ей следует сделать(если сделать пример утрированым, то можно сказать, «почему функция executeSql(sql: string) заставляет меня тюнинговать запрос вместо гарантии, что все само оптимально выполнится?» в данном случае можно заметить, что этот контроль передается клиенту АПИ, он может вариировать любой sql запрос, а значит и отвественность за то, какой из вариантов передвать лежит на клиенте), потому что надо иметь много различных вариаций обработки данных, если бы вы выделили «сложный» код с оптимальным sql условно в репозитории вы бы на выходе получили бы интфрейс который подразумевает, что клиенту уже этой сущности на надо парится с перформансом генерируемого запроса, но при этом вы ограничите контрактом/типами то, как можно работать с этой сущностью.

Типы в мейнстрим языках — это просто бирочки, ярлычки, аннотации, «комменты»

может мы в этом моменте и расходимся, что я вкладываю чуть большее в это?

если ты в аутсорсе, у тебя семь пятниц проектов на неделе,

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

типы вообще ничего не констатируют, в общем случае (разве что в настоящих функциональных языках программирования)

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

Но если мы идем в микросервисы, то вот честно, я так и не понял зачем зачем Go типизированный :)

если чисто логически взять функцию из 100 строк и разделить на 100 функций по одной строке, то мы получим 100 сложнозавязанных функций с кучей инпута-аутпута, который был в локальном контексте, сложность в одном месте перераспределилась на сложность связей между ними — в итоге все равно надо будет в голову грузить всеми компонентами, работая с ними, поэтому этот пример ортогональный вопросу.

значит у вас и id колонка не обязательна

зависит от ...
если ее нет — это тоже id. обычно о том что этот объект — пропустить, исключить из обработки обработчиком которому — нужен id

Программирование — НЕ математика.
Общими случаями занимается наука
А ремесленники занимаются конкретикой, частностями.
Программирование — ремесло.

пытаясь понять пример что вам надо

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

а ведь это 2 разных ситуации

ну да.
в общем случае — сколько проектов — столько и этих разных ситуаций.
хотя если точнее — то сколько мест использования в коде байт в колонке id — столько и ситуаций

Какой бы вы не делали динамический по структуре обьект, он все равно обрабатывается статическим

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

просто в случае с типами она констатируется

зависит того — что именно заложено в бирочку тип.
если там заложено например — по адресу будет 4 и только 4 байта
то эта бирочка никак не запретить написать сложение «роста» и «возраста» и отдать полученные 4 байта как «вес»

в ином случае мы либо держим в голове кеш

а вы все равно его держите. говорит ли вам тип что там есть колонка id или не говорит :)

«можно передать обьект с любым набором ключей»

и берете и передаете.
вам в конкретной строке все равно надо одно или парочка ключей.
какая вам разница, для написания этой строчки кода что там еще какие тьмы ключей, по которым лежая объекты с тьмой ключей
вам надо для примера выше один
height
нет такого — значит и нечего у этого объекта прочитать из его height
есть? значит, весьма вероятно это и есть — рост.
как байты записали? 178 или «178 см» или {size: 178, measure: «м» } ? а как — надо?
а может и — и операции добавить к объекту? он то о себе точно будет знать — как надо, и что в нем лежит.
а в measure может лежать — «м»? а «м» это метры или мили? а, а, а,...
вот в конкретном проекте и разруливаются эти а

я хочу немного шоколада, я же могу передать в функцию этот запрос?

можете.

или он с такими не работает?

так это ж к вам и вопрос — вы хотите что попало засунуть куда попало и получить шоколад?
ну, так обычно не бывает.
вы — должны что вы передаете. и должны знать — где из этого получится шоколад

то есть зависимость от структуры будет независимо от того, указали ли мы тип или нет

конечно. байты надо трактовать опредленным образом

если функция декларирует какой-то тип, но все равно валится, значит она не описала, что ей надо нормально

см выше — тип ничего не декларирует, точно так же как название переменной size. туда положили — вес :) а тип одинаковый у них — FourBytes

К первому случаю могу лишь сказать, что типизация тоже требует понимания что ты делаешь

Любой код требует понимания что ты делаешь.

но не надо приравнивать знание домена и колупание во всей кодовой базе

а зачем колупаться во всей кодовой базе?
но да, абстракции — текут. Всегда.
Часто — абстракции на старте проекта не соответствуют требуемому описания домена с развитием проекта.
так что колупаться — придется.

Именно такая необходимость и приводит к тому, что «дебажим неделями»

Стоимость=время.
Китайские ботинки — носятся три месяца.
Канадские — 3 года. Но китайские стоят — копейки. Канадские на два порядка дороже.
Выбирай сам — созданием сверхнадежных конвенций, в частности в виде зануднейшей системы типов. Которые — потом придется ломать, если проект взлетит и будет развиваться.
Или — купить новые ботинки, за копейки, потому что неделя дебага одним программистом — копейки, в сравнении с месяцами работы аналитиков и заторможенной эффективностью команды программистов.

Понимаете — есть наука, а есть ремесло.
Наука вне экономики. А ремесло — всегда под ее давлением.

можно таким же образом в безтиповом коде написать тучу фабрик

да. и фигачат :) отсутствие статической типизации — не мешает :)

А вот это плохо,

Плохо то что люди — смертны. Мне не повезло, я тоже человек.
А то что вы пишите — мелочь. Как мытье посуды.

я вот например понимаю, что figure это набор вершин и ребер

не спешите додумывать то чего не знаете — всегда говорю
есть даже такая притча у Ошо
я понятия не имею что такое figure. это может быть даже не растровое изобржение. а
The figure is considered to be inflated by double counting. — показатель
а draw — выдать колонку для его отображения в колоночной диаграме

никакой информации в drawFigure(figure) без контекста — нет
это просто какие-то буквы, каляки-маляки

потому что в типизации мы явно отображаем как мы декомпозировали обьекты,

что мы отображаем типами — зависит от возможностей системы типов и того что ими отобразили
но если мы отобразили декомпозицию объектов, то в случае, а это почти всегда — ее придется менять в будущем — вот и получим — войну с типами.
чем детальнее отражено что-то в типах — тем жестче конструкция построенная на них.
жестче чем наследование
если домен — не меняется, что обычно в научных доменах — все отлично
если же меняется — что в прикладном, для бизнеса ПО — то ой

говорят про удобство рефакторинга.
Мне это напоминает шутку знакомого, у которого Субару, а СТО знакомого, на другом конце города:
И как бы это я без машины успевал заскочить на СТО?

В примере с орм они вам гарантировали, что вы получите ожидаемый результат

Ничего нам никто не гарантировал в вашем примере. А пообещали что ответ будет в такой-то упаковке.
Обещать — не значит жениться.

я говорю про масштабирование в рамках одного проекта. несложно если код маленький

Если кода много — то в любом случае вам придется его декомпозировать на модули, слои абстракций и т.п. Дробить до — «функций в 5 строк». Что вам в функции в 5 строк может быть непонятно? :)
А когда эти абстракции потекут — вам придется делать что-то с системой типов, если она жесткая. а потом — с кодом, потому что типы то — ничего не делают, а напомню — бирочки
а потом — и тесты переписывать :)

потому что это можно одним контекстом в голове держать и работая с кодом просто все держать в голове,

Пишут, объем оперативной памяти чел мозга — одинаковый, и от IQ не зависит
Почему же люди такие разные, способностям держать что-то в голове и оперировать с этим?
А типы — тоже там же надо держать :)

если чисто логически взять функцию из 100 строк и разделить на 100 функций по одной строке, то мы получим 100 сложнозавязанных функций с кучей инпута-аутпута

Как-то встречал пояснение, почему в Haskell переменные не называют как положено, а как в математике, одной двумя буковками.
Не только в силу математики.
А и потому что функции там вот такие мелкие и есть. И переменные эти — смысла никакого не имеют.
А увязывается все в цельную конструкцию — типами.

Уже писал
Системы типов которые хоть что-то гарантируют — в тру функциональных языках
в мейнстрим языках по большей части типы — это карго культ, и только в имеющих компиляторы в маш код — подсказки компилятору.

А программирование я потому и называю не инженерией, а филологией, потому что много коллег встречал и встречаю, которые озабочены, которым в кайф выяснять где у нас какие части речи, как они соотносятся, склоняются, и т.п.

бОльшая же часть людей — просто говорит на своих языках.
Так и количество программистов на ЯП с дин типизацией — растет в процентном соотношении.
Они просто — «говорят». Когда осмысленно, когда не очень.
И им пофик какого типа объект получили.
Есть у него id или нет — это интересует

Как парикмахера не интересует содержимое голов :) он типизирует людей — по своему

зависит от ...

структуры вызывающего кода, даже если типы не декларированы

хотя если точнее — то сколько мест использования в коде байт в колонке id — столько и ситуаций

но ведь в коде вызывающая функция зависит от вызываемой, а не наоборот, это если где то вызывать внутренний метод, тогда мы можем иметь эту high cohesion иначе это будет high coupling.

если там заложено например — по адресу будет 4 и только 4 байта

значит ей просто важно, чтобы это было 4 байта и все. если она захочет более специфичного, то она ограничит инпут. Можно ли разграничить Weight от Height? Можно. Отвественность в данном случае лежит только в моменте конструирования Height(178), Weight(70), после чего операции Weight + Height и прочие будут статически не разрешены, то в данном случае ограничение даст гарантию. В таком случае функция может явно потребовать чтобы это был Weight, точно так же как функция «+» требует чтобы это был (T a, T b). Если какой-то метод требует int, мы тоже можем передать туда Weight и Height, потому что это более общий тип. В некоторых языках вроде F#(жаль, что редких) есть встроенные синтаксические возможности работать с единицами измерения, там еще проще работать с этим. (Вспоминаятся история про сбой одного аппарата из-за того, что там был передан дюйм, хотя требовался сантиметр)

так это ж к вам и вопрос — вы хотите что попало засунуть куда попало и получить шоколад?
ну, так обычно не бывает.

Значит не могу.

вы — должны что вы передаете. и должны знать — где из этого получится шоколад

Да, то есть завязаность используюещего кода на используемый есть, даже если нет декларации типов.
А шоколад ли — вопрос, там в коде происходил запрос с 4 байтами в другую систему, и что-то вылезло наружу после пару циклов, это шоколад? Или что-то другое коричневое?:)

а зачем колупаться во всей кодовой базе?

См. пример выше

никакой информации в drawFigure(figure) без контекста — нет
это просто какие-то буквы, каляки-маляки

Согласен, а в figure: Figure, where Figure: {nodes: Point[], edges: Point[]} при drawFigure как метода класса, например, Canvas2D?

чем детальнее отражено что-то в типах — тем жестче конструкция построенная на них.

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

ее придется менять в будущем — вот и получим — войну с типами.

как и с нетипизированным кодом лучше выделять более стабильную, доменную сущность, если так не выйдет, то и в дин программировании прийдется воевать коду с кодом, там поменял обработчик под новую структуру, а там забыл. Сегодня figure в нашем примере вы обрабатываете так for (let node in figure.nodes), for (let edge in figure.edges) (условно), а потом бизнес сказал, что это надо чтобы достаточно было задать только edges, но попросил еще цвет им задавать, вы уберете с кода, nodes, добавите обработку цвета в edges и пойдете во все места использования убирать nodes и простановку edges — в итоге все равно получили завязанный код — надо и туда лезть и туда, чтобы одно это действие сделать. Жесткость системы «нетипов» будет ровно такая же.

Ничего нам никто не гарантировал

Он возвратил условно IEnumerable — я имею гарантию, что если не произошел ексепшен (который есть в контракте), то я получу итерируемый обьект с обьектом Product — это я и имел ввиду

то в любом случае вам придется его декомпозировать

Да, и важно это сделать рационально

Что вам в функции в 5 строк может быть непонятно? :)

Можно взять мой пример со 100 функциями по 1 строке — по идее максимально все понятно в одной отдельной — но что-то все равно не то. Она зависит от других функций и надо смотреть в них, поменяли какую-то функцию — через эту уже другие данные текут и в каких-то случаях неправильные.

А и потому что функции там вот такие мелкие и есть. И переменные эти — смысла никакого не имеют.

Такой момент есть, тип и контекст использования забирает часть названия идентификатора. Та даже банально add (numberA, numberB) vs add(a: number, b: number). как тут еще можно назвать? add(sobachki: number, kotiki: number) ? Но зачем?

Так и количество программистов на ЯП с дин типизацией — растет в процентном соотношении

Причин этому много может быть.. и не всегда указывающих на их(ЯП) правильность в контексте обсуждения

он типизирует людей — по своему

Да, ему надо только hair условно говоря, все head с brain он и не требует, но если надо hair, то уже прям required. Если прийдет туда лысый или ежик или зеленокожий инопланетянин — ну так он их пошлет.. а зачем 100 раз стукать кому попало, если можно было написать — «вход только с волосами»? это хорошо еще он хотя бы посылает их, если он будет пытаться стричь то, что на самом деле не подходит, то тут могут ой какие проблемы вылезти, он может пытаться порезать человека ведь ему сказали обрабатывать клиента именно таким образом :)

структуры вызывающего кода, даже если типы не декларированы

код просто вызывает, и передает байты
его структура от трактовок байт не зависит

но ведь в коде вызывающая функция зависит от вызываемой

зависит от смысла слова «зависит»
вызванная функция оставляет байты, вместе вызова, или — меняет байты по переданным ей байтам, которые она понимает как адрес в памяти

значит ей просто важно, чтобы это было 4 байта и все.

неизвестно, что ей это важно
она может только с первыми тремя битами работает.

операции Weight + Height и прочие будут статически не разрешены

можно конечно.
если потом не появится потребность в операции Weight + Height для вычисления какого-то коефа.
а можно просто не писать weight + height
смысл же названий подсказывает что это какой-то абсурд :)

то в данном случае ограничение даст гарантию

гарантию чего? что операция + недоступна для этих значений?
ну да.
Мне б такие проблемы, где такая гарантия что-то решает :)

есть встроенные синтаксические возможности работать с единицами измерения, там еще проще работать с этим

есть.
только в домене — типов куда больше, и их придется — конструировать, чтобы получить такие гарантии.

Значит не могу.

можете. просто результат будет — хз :)

Да, то есть завязаность используюещего кода на используемый есть, даже если нет декларации типов.

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

вопрос, там в коде происходил запрос с 4 байтами в другую систему

так это вопрос к коду той системы. точно такой же как к коду собственной.

Согласен, а в figure: Figure, where Figure: {nodes: Point[], edges: Point[]} при drawFigure как метода класса, например, Canvas2D?

и, в чем вопрос? вы не знаете какие поля должны быть для корректной работы Canvas2D?

или вопрос — как не зная ничего о конвенциях Canvas2D — сесть и написать что-то осмысленное, и чтобы вся дока по ней была выражена в типах?

так все равно ж придется — знать.
даже если типы вам подскажут о Figure.
вы одну в draw, другую в draw — опа, а как чтобы первая лежала под второй?

В них отображено то, что надо принимающему коду

нет
в них отображено то что отображено
а что надо принимающему коду — то надо
и в общем случае — никакой гарантии что
вы верно поняли что отображено, так как задумывалось тем кто написал бирочку
и на бирочке написана однозначная и исчерпывающая информация тому что надо коду
и вы даете это, и то что вы даете, в точности соответствует тому что написано на этой бирочке

это все равно будет жесткая конструкция

она будет менее жесткая чем с бирочками

мы все равно не получим выгоды

весь мир, и я в частности получает ого какие выгоды, а вы не получите :)
ну ок.

как и с нетипизированным кодом лучше выделять более стабильную, доменную сущность

Лучше да, быть богатым и здоровым, чем бедным и больным
Сколько времени дают на — анализ и проектирование?

В NASA — пару лет. и все равно бортовое ПО спутников и марсоходов нет нет да и зависнет.

то и в дин программировании прийдется воевать коду с кодом,

Не понимаю о чем вы. Что на С, что на Java, что на C# - точно так же дебажил — воевал с кодом.

там поменял обработчик под новую структуру, а там забыл

писать просто надо так — чтобы не было размазано — там, сям а в одном месте
А оно так получается — потому что декомпозиция — такая же. бест практики по ней — те же.

Когда же у вас типы обругают, черте с какого места — то да, не забудете. И будете разбираться, какого лешего аж вон там — тоже напрямую пишется в этот объект??
и придется да, гонять по всему коду.

а потом бизнес сказал,

то что не лезет в вашу систему типов.

я то перепишу, те места, и баги отловлю. а вам придется — перепроектировать систему типов вначале. или, если она примитивная — то она вам ничего и не гарантировала.

Он возвратил условно IEnumerable — я имею гарантию

какая разница как называется то — по чему вы собрались итерироваться?

Да, и важно это сделать рационально

ну да.

Можно взять мой пример со 100 функциями по 1 строке — по идее максимально все понятно в одной отдельной — но что-то все равно не то.

почему ж?

потому что непонятна абстракция более высокого уровня.
Если вы не понимаете что такое бухглатерский счет — то типы вам не помогут написать код который пройдет их проверку но делает — чушь.
А если вы понимаете что такое бухглатерский счет — то вы понимаете и что делает эти 100 функций в одну строку и найдете ту, которую нужно изменить

Не мое, неоднократно встречал у гуру программирования:
знания домена программистом делают его на порядок эффективнее просто кодера

вот и приходим, если нет возможности знать домен — тогда да, наверное типизация и поможет вслепую, по названиям типам тыкать, авось шоколодка будет :)

как тут еще можно назвать? add(sobachki: number, kotiki: number) ? Но зачем?

так и с типами происходит.
IEnumerable — чего именно IEnumerable ? а-а-а IEnumerable .T. надо бы.
потом о, ковариантность и контраварианость надо бы еще указать, потому что обработка этого T отказывается принимать наследника, предка, ...,
и т.д. — а код когда писаться будет?
а, бытенько и легко после этого?

так я уже написал и в прод запулил :)

Да, ему надо только hair условно говоря

угу, а у обработчика стоит «White only» типа
а потом — собаку попросили постричь. опять типы не те.

«вход только с волосами»?

конечно, если бы сразу тип — ТоЧтоМожноСтричь
причем это будет более точно, чем ТоЧтоСВолосами, потому что не все что с волосами можно стричь. и еще придется определять что такое — Волосы
а стричь — уже опеределено, это собственно то действие ради которого и отправляется нечто, чтобы над ним произвели действие — стрижку

Но я такого кода не встречал. и понятно почему — чутье подсказывает И пишущим на ЯП с стат типизацией, что это будет лютый удар по перформенсу разработки
и тьмы преобразований типов в коде, где, странно, будем — избавляться от такой типизации в рантайме :).

Но, никаких запретов нет — попробуйте типизировать все до уровня — доменных понятий. тогда — гарантии начнут появляться :)

он может пытаться порезать человека ведь ему сказали обрабатывать клиента именно таким образом :)

от этого тип — не защитит. это ж — реализация. округлили отбросом копеек, а надо было — банковским округлением. и усё.

а кто домен не знает, и в спеке ему не прописали — так и сделает — выберет не тот способ округления.

а тот кто знает — выберет правильный. независимо от ЯП и его возможностей по типизации. и спеки даже ему не потребовалось

код просто вызывает, и передает байты
его структура от трактовок байт не зависит

можно везде как any передавать, но избавит ли это нас от необходимости приводить кусок кода что передает и тот, что обрабатывает в консистентность?

неизвестно, что ей это важно
она может только с первыми тремя битами работает.

как быть если ей надо 5?

гарантию чего? что операция + недоступна для этих значений?
ну да.
Мне б такие проблемы, где такая гарантия что-то решает

ну, это как инструмент, который дает то-то, требует исилий таких-то. если это нужно, то почему бы не использовать? выше привел пример где апдейт несовместимых величин привел к проблемам. например им помог бы такой подход?

а можно просто не писать weight + height

всегда ли это будет ровно такое же название? да и почему нельзя, а в друг в домене это составляет какой-то коэффициент ожирения?

можете. просто результат будет — хз :)

поэтому будем заходить в цикл разработки: дебаг, рытье кода, постукивания головы об стену )

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

и как с ними работать, изучать все состояния байт после вложенных операций?

и, в чем вопрос? вы не знаете какие поля должны быть для корректной работы Canvas2D?

когда есть формальное описание в типе это проще понять, «вместо тысячи слов», а точнее примеров о том какие данные передаются мы сразу видим модель данных и можем в полной мере из простого декларативного описания как с этим работать, естественно нюансы технического плана, перформанса и прочего мы читаем из документации — тут должен уже быть баланс, доказывать типами такие вещи дорого, а нормально описать типами хотбя контракт библиотеки не так уж и дорого.

никакой гарантии что
вы верно поняли что отображено, так как задумывалось тем кто написал бирочку

тогда отвественность используемого кода должна переходить в использующий? ее так или иначе надо разделить, поэтому использующий код будет работать базируясь на том, что используемый дает гарантии, в ином случае будем через все слои решать вопросы в базе данных или структуру данных иметь ровно такую же как в формате данных для транспорта и так далее. Если используемый код не исполняет свои гарантии, то что делать? делать заплатки в использующий? или все же довести его до гарантии требований к нему? (речь о 2 модулях в текущем проекте)

она будет менее жесткая чем с бирочками

как это оценить? я привел пример почему де-факто она такая же, в аргументы используемого кода вкладывался тот или иной смысл (используемый модуль не делает полную перепроверку сущности, вместо этого он его спокойно начинает итерировать, вызывать его как функцию и так далее — это все примеры того, что этот тип вы де-факто закладывали в аргумент, когда писали код а значит меняя итерируемую вариеблу/константу на функции вы подразумеваете, что это уже функция и надо везде передавать функцию), только в одном случае он явный, в другом неявный.

весь мир, и я в частности получает ого какие выгоды, а вы не получите

не прям уже весь. выгоду можно извлечь, если такой майндсет удобнее, так привычнее, это позволяет иметь достаточное качество/изменяемость/читаемость, это легче в голове конструировать — поэтому тут спорить смысла нет. Лично я тут писулькаю про типизацию потому что мне этот подход удобнее, я не дебажу неделями, при какой либо проблеме проверяю в чьей зоне отвественности она вылезла и довольно негеморно фикшу. Да, типизация разная бывает, особенно если про старые версии яп говорить — может не хватать чего в плане констреинтов, где-то надо свистопляски проделывать, чтобы можно было разными вариантами типа параметризировать, если это прям вообще неудобная система типов, то я даже подумаю стоит ли ее юзать или все же на динамику с jsdoc залезть. Но пока я не столкнулся с таким ощущением. Но с js ситуация такова, что контракты там надо писать максимально експлисит — методы аргументы, прописывать декларативные конструкции, иначе получаем тучу гемора с тем чтобы понять какие аргументы принимает тот метод, почему не работает и так далее — нет никаких точек фиксации какого-то ограничения состояния данных, где-то выше в ветке человек писал, что в любой программе на динамическом языке все равно приходиться в каком-то роде писать эмуляцию типизации, это, я бы сказал, автоматом приходит.

Сколько времени дают на — анализ и проектирование?

но это же необходимые этапы, хоть в каком-то обьеме, с, конечно же, соотвествием проекту. Но у нас же не «аутсорс 5 проектов в неделю», где не надо в домен вникать?
А вообще отвечаемое сообщение чем некоректное? Вы бы согласились например использовать библиотеку, которая раз в 2 дня ломает схему данных без какой-либо пользы? Для библиотек это заметно, для внутрипроектоного кода не так сильно, но тоже имеет место быть — перелопачивать тесты, менять все места использования и так далее — незавидная история. Другой вопрос почему так просходит? Возможно потому что в интерфейс выделен код, который вместе использующим должен был на самом деле быть где-то вместе в модуле инкапсулированным?

писать просто надо так — чтобы не было размазано — там, сям а в одном месте

пример с createValidator надо только в одном месте использовать? Хорошо, а если то одно место в нескольки используется?

и придется да, гонять по всему коду.

по местам, что покраснели. а если они не по краснеют и то место где не поменяли вызовется только на проде?

а вам придется — перепроектировать систему типов

если все завязано на все — то да, но так же не делают, такое поделие с архитектурой ничего общего не имеет — по сути те же «100 функций с беспорядочными связями». в таком случае появляется вопрос: а что человек проектировал? ведь цель проектирования в том числе и чтобы такие изменения были максимально безболезненными. с другой стороны: а что если человеку, который вышеупомянутые фабрики/билдеры/мапперы сделанные безцельно и сильнозавязанные сделал на js? немного ли проще это? так может «перепроектировать все в результате какого-то изменения» это вопрос ортогональный типизации?

какая разница как называется то — по чему вы собрались итерироваться?

я привел пример самой базовой итерируемой сущности (опустим duck typing с GetEnumerator) она дает гарантию, что мы можем итерироваться. есть ли разница? ну вы можете попробовать начать итерироваться по чему угодно, но у вас не выйдет, если мы говорим по C#

потому что непонятна абстракция более высокого уровня.

потому что нет никакой пользы так делить, просто попробуйте представить эти 100 функций. с ними работать надо ровно так же как и со всей функцией. меняются они ровно таким же жизненным циклом как и вся функция. мало того, они потребуют писать 100 файлов юнит тестов в каждом из которых надо делать сложный сетап данных, проверять почти ничего не делающий функционал и также проверять сложный результат данных, но смысл? этот пример был к тому, что описываемый подход где мы копаем во всей имплементации проекта (чтобы разбираться что можно передавать, как предлагалось) напомнило мне этот случай — ведь такая же связанная каша по факту, даже если мы и грамотно декомпозируем код, но без нормального указания контрактов — цикл работы с ним похожий будет.

а код когда писаться будет?

я же просто показал пример, почему и куда из идентификаторов исчезают части именований.
«раз-раз и запушил» — это очень комлпексный показатель + связанный с субьективным опытом, я так же могу в той среде, где я пишу код. а в js можно например сидеть час дебажить почему структура тех данных в этом состоянии исполнения имеет такое значение, а не нужное, и так далее из того, что я выше перечислял.

угу, а у обработчика стоит «White only» типа
а потом — собаку попросили постричь. опять типы не те.
конечно, если бы сразу тип — ТоЧтоМожноСтричь

если такой тип полезен в домене, то почему нет? а как в динамическом это должно выглядеть? если парикмахеру надо человек, значит также надо будет конструировать/переделывать обьект так, чтобы получить рабочий параметр функции.

от этого тип — не защитит. это ж — реализация. округлили отбросом копеек, а надо было — банковским округлением. и усё.

я привел абстрактный пример, вы взяли из него полезный для доказательства своей мысли пример, с которым я не спорю, а я все же предложу то, что я имел ввиду: ожидалось получить из функции результат person: {name: string, money: decimal}, получили person: {name: «Vasya», totalMoney: 100500}, считали с него money, записали куда-то и в итоге нет бабок у юзера, а все потому, что где-то в одном кейсе забыли поменять на money и записали такое значение в обьект.

а тот кто знает — выберет правильный. независимо от ЯП и его возможностей по типизации. и спеки даже ему не потребовалось

да, я где-то тоже писал, что есть моменты которые ортогональны вопросу

можно везде как any передавать, но избавит ли это нас от необходимости приводить кусок кода что передает и тот, что обрабатывает в консистентность?

я не понял значения слова «консистентность» в этом контексте

у вас задача — получить арифметическую сумму двух чисел
вы пишете:
c = a + b
подставляете 2 и 3
c = 4
задача — НЕ выполнена. Цель, предназначение кода — НЕ достигнуты
типизированы у вас a,b,c или нетипизированы — с должно быть 5 в результате выполнения этого кода.
даже если a + b, у которых есть магический метод toNumber() переопределены операции addNumber и ЯП все это знает, и превратит в действительности c = a + b в
c.setNumber(a.addNumber(b.toNumber()))

цель кода остается той же.
Что такое — консистентость?
и при чем к ней — статическая типизация?

как быть если ей надо 5?

а если стопять? а если метеорит упал?
вы предлагаете рассмотреть все явления во Вселенной?
я вам привел пример что тип — никак не указывает на то что надо коду, в который мы передали нечто помеченное этим типом. В общем случае.

ну, это как инструмент, который дает то-то, требует исилий таких-то. если это нужно, то почему бы не использовать?

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

всегда ли это будет ровно такое же название?

Мне неизвестны даже все существующие на данный момент случаи в коде.
А вы мне задаете вопрос — о том что будет в мировом программном коде?

а в друг в домене это составляет какой-то коэффициент ожирения?

зачем вы мне приводите пример, который я же и привел перед этим :)

поэтому будем заходить в цикл разработки: дебаг, рытье кода, постукивания головы об стену )

заходите с другой стороны конечно :)
мы ж не в одной команде, и тем более я вам не тех лид указывать с какой строны вам заходить
никакого «мы» тут нет.

другого в разработке я почти за 30 лет не встречал, порядок такой
требования, анализ, код, отладка, код, отладка, измнения требований, код, отладка, ...
код и отладка — это всегда битие головы об стену, и рытье кода

но, может у кого другой опыт разработки, я то что, ну писал коммерческий код на С, и на асме, писал и на 1С, писал и на C#, и на Java, и на пыхе, и на джс, и бек, и GUI, и WebUI, писал и под несколькие БД, на их хранимках, разных семейств, — и эл магазы, и орекстровку провижионинга в облаке на VMware инфраструктуре — слишком маленький опыт, не мне джуну обобщать его на мировой опыт разработки.

У вас другой, расскажите о нем :)

и как с ними работать, изучать все состояния байт после вложенных операций?

не доводилось ни разу изучать все состояния байт.
не понимаю вашего вопроса.

когда есть формальное описание в типе это проще понять,

понять — это затратить мозговые усилия.
если формальное описание не выражает того что в действительности — то затраченные усилия никак не окупаются.
«На сарае х-й написано. А там дрова»
Это о формальных описаниях известно даже не программистам
Только действующий код является источником — правды.

Проблему ж истинности утверждения да, копают давно.

и можем в полной мере из простого декларативного описания

раз можете — значит так и делайте
я не встречал в дикой природе тех кто может.
поэтому и было потусовался среди функциональщиков, они вроде да, могут.
но узнав стоимость — отказался

вы — можете. Делайте!

тогда отвественность используемого кода должна переходить в использующий?

Когда как. Зависит от ...
Я наукой не занимаюсь, за общими ответами на общие вопросы — это к ученым.

как это оценить?

скоростью разработки, есественно
так все и оценивают :)

Лично я тут писулькаю про типизацию потому что мне этот подход удобнее

О вкусах не спорят. Удобнее — пишите. Мое кредо такое же — писать надо на том ЯП, в той парадигме которая тебе удобнее. Потому что это и есть твоя основная часть жизни — работа.

но это же необходимые этапы, хоть в каком-то обьеме, с, конечно же, соотвествием проекту.

этапы как и роли людей в проекте — могут быть совмещены.
могут переставляться. и т.п.
зависит от ...

Но у нас же не «аутсорс 5 проектов в неделю», где не надо в домен вникать?

не знаю про «у нас»
у меня да, я в аутсорсе не был. и всегда начинаю с вникания в домен.
а зная риски разработки — так вообще начинаю с конца проекта.

Вы бы согласились например использовать библиотеку, которая раз в 2 дня ломает схему данных без какой-либо пользы?

зависит от ...
как и то что я бы делал в таком случае

Дочитал ваш комент до конца.
Больше не вижу что добавить к сказанному ранее и выше

It depends on...

Согласен, обсуждение перешло в срач и все остались при своем мнении, смысла в таком же формате продолжать нет) Вспомнил случай когда надо было достаточно сложный механизм преобразований проделать (код для определения всех возможных значений в коде с учетом полиморфизма и так далее), но времени маловато было (для учебы), сначала для скорости решил для себя написать на js, сначала все выглядело по красоте, потом в процессе добавления возможностей пришлось столкнулся с апдейтом схемы и так далее и тут почувстовал «боль», стало явно не хватать явной схемы данных в отдельных местах. Стало более очевидным, что потратив время на нее было бы в итоге быстрее

где срач, какой срач? :)

обмен мнениями — ну да.

а вот вера в то что в результате кто-то из обменивающихся должен изменить свое мнение — ну то такое. наивное :)

просто да, видел не раз на практике что такое «паралич анализа», или он же — буриданов осел
вопросы задает умные, рассуждает — а если то, а если сe, а по науке так, а вот была книга-статья где написано сяк, а я вот вчера подумал, а сегодня я передумал, а, но, и как бы да, но хорошо бы, и не будет ли плохо, ,.. ..,

как кто-то с миллиардеров сказал — если для действия ждать всей информации — никогда не начнешь действовать.

знаете как нужно? делайте! что тут обсуждать?

P.S.
Кстати знаете кто дает хорошие гарантии, помимо контрактного программирования, (которое не взлетело, потому что такого уровня гарантии по той цене что нужно платить — мало кому нужны)?

DSL — domain-specific language
А DSL почему не взлетели?
А потому что изменения в DSL — еще дороже чем при контрактном программировании
Недочет, ошибку, неполноту в DSL костылями не обойдешь
И новым программистам надо дольше входить в проект.

А чем более продумана и развита система типов в проекте=приближается к описанию домена, тем она ближе к DSL
Одной ведь из киллер фичей ФЯ и называется — легкое создание DSL!
Да, потому в них что системы конструирования типов позволяют делать это «из коробки», без всяких либ.

Почему нет массового перехода на них, раз кругом — О-о-о, статическая типизация, повышает надежность и качество кода, и т.д.?
Дорого потому что. потому что надо ху*як, ху*як и в продакшн.
И на джавах с сишарпами — тоже так же и делается :) и тесты нередко пишутся, и сломавшиеся фиксятся — потом, а не по TDD

Так что если хочется гарантий от статической типизации — надо переходить на ФЯ.
В мейнстрим ЯП просто и многих средств нет, даже если вот захотеть.

ФЯ часто просто не совсем хотят учить сами по себе, надо чуток головой еще пошуршать, время потратить, а ведь вакансий мало по ним, так зачем же учить, если можно актуальные вещи лучше подтянуть за это время — в итоге замкнутый круг.
DSL- ну тут смотря какая, иногда они прям просяться и есть реально полезными и стабильными по структуре, а иногда притянуты за уши и меняются постоянно, иногда вырождаются в просто симулирование кода, чтобы все кейсы покрывать

ведь вакансий мало по ним

их и будет мало

потому что там тоже нет никакого чуда.
при том что мечта о статической типизации доведена до наивысшей точки. возможной на сейчас, и имеющей практическую ценность.

в итоге замкнутый круг

Всегда так и было.
О мире идей — Платон горевал, а Будда на этом религию построил — указав что мечтания и есть причина страдания :)
ну или еще проще
Чтобы не разочаровываться — не надо очаровываться.

иногда

да,
it depends on

Речь идет о личном опыте и внутреннем ощущении

то JS и TS старался бы забыть как страшный сон.

так TS и сделал на дотнетчиков и джавистов :)

программирование на дин ЯП требует самодисциплины, если нужен хороший, надежный код.
Понятно что за годы программирования на Джаве или C# ее не выработалось, и использование опасной бритвы, хождение по лестницам без перил — вызывает много травм.

такой вот парадокс с дин ЯП.
С одной стороны низкий порог входа, и любой школьник через месяц уже может писать что-то работающее на питоне, джс, пыхе
а с другой — чтобы оно было не просто работающее, а читабельное, устойчивое к рефакторингу, и т.п. — требуется ясность и четкость мышления, уровень «мидл+», которым в коде и на легаси Джава — радуешься: «повезло!»

TypeScript — строгая типизация на системе типов JavaScript. Это как связать руки тому, у кого уже ноги сломаны.

TypeScript хорош только в кусочках кода, размером с экран, но в больших проектах начинается зацепление типов, это дополнительный coupling.

1. Не любая конструкция джаваскрипт может быть типизирована тайпскриптом, а то, что это надмножество — это просто маркетинговое вранье.
2. Иногда он неправильно обрабатывает типы и находит ошибки там, где их нет, а пропускает там, где они есть.
3. Основные ошибки они не в системе типов, а в логике программы, в неправильной декомпозиции, в анипаттернах, которые можно без труда покрыть типами и проблема не решится. Разработчики находятся под гипнозом ложной надежности и они меньше заботятся о тестах и ревью кода.
4. В рантайме проверки типов нет, а при взаимодействии клиента и сервера или микросервисов друг с другом все проверки нужно делать руками.
5. Разработчики бегут от сложности предметной области в уютный мирок обсуждения типов в курилках, это достаточно круто звучит все и делает видимость сложного и серьезного дела, чтоб не концентрироваться на душных задачах бизнеса.
6. В нем нет автовывода, а вместо него все много раз дублируется и захламляет код, снижая его читаемость и понятность.
7. Тайпскрипт некоторые идеи передаст в js и отомрет, тогда нужно будет переписывать проекты, как уже было с кофескриптом и многими другим суррогатными языками.
8. Нет четкой спецификации синтаксиса языка, она вообще отсутствует и язык состоит из отдельных фич, которые можно включить и выключить в конфиге.
9. Тестирование решает те же проблемы, но делает это надежнее, потому, что проверяет не только сигнатуры, но и сложное поведение, в том числе асинхронное.
10. Ну и как показал уже Илья в докладах — это экономически не выгодно. Деньги потраченные на юниттесты дают лучший результат.

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

Любая, потому что есть тип Any. Любая система типов — набор ограничений, и в TS этот набор сильно получше чем в некоторых языках, так что если типы мешают писать код, то дело не в типах, а в том кто пишет. Про надмножество это действительно не вранье, потому что с any можно писать код и в TS, как в том самом джаваскрипте, к этому в добавок идёт возможность ползоватся типами. Мол «типы нинужны» это сильное заявление, но ещё ни один джаваскриптизер не написал большого продукта, без ошибок которые бы не ловились системой типов.

Иногда он неправильно обрабатывает типы и находит ошибки там, где их нет, а пропускает там, где они есть.

Конечно, а что вы хотели от языка без своего рантайма которы бы это форсил? Написать кривой каст из кривого жс-фреймворка который отдаёт бог весть что и чтобы это работало как надо? Не, извольте подключить либу которая это делает(а она есть).

ошибки они не в системе типов, а в логике программы,

вот конкретно вот эта строчка показывает что томик теории Б вы даже не видели и не слышали что это такое. Типы — способ зафорсить определённую логику программы. Например, тип Int форсит то, что сюда не будет передано ничего кроме инта, если не использовать кастов. Есть такие типы которые форсят, например, что переданная реализация алгоритма сортировки действительно сортирует и действительно за n log n. Если вам об этом рассказывали, то не значит этого не существует. Типы — инструмент для того чтобы проверять логику программы, если им не пользоватся, ничего и не будет.

можно без труда покрыть типами и проблема не решится.

как я уже написал — проблема неправильного применения.

В рантайме проверки типов нет, а при взаимодействии клиента и сервера или микросервисов друг с другом все проверки нужно делать руками.

Либы — есть, руками не нужно.

бегут от сложности предметной области

Для сложности предметной области есть специально обученные BA. Ну и архитекторы, остальным держать всё в голове не только бесполезно но и вредно, вот тогда они начинают входить в состояние:

и они меньше заботятся о тестах и ревью кода.
чтоб не концентрироваться на душных задачах бизнеса.

Они и не джолжны концентрироватся на задачах БИЗНЕСА, на задачах бизнеса концентрируются BA, менеджеры и прочие, разрабы решают технические задачи. Если они решают «задачи бизнеса» это уже не разрабы. Я вот не видел бизнесмена которому для развития бизнеса нужно обновить версию вебпака. А вот более низкая комиссия при оплате онлайн, или меньше косты на вэб-хозяйство, или интеграция с сервисом доставки — вот это надо. Но только эти вещи связаны с решаемыми техническими задачами совсем не прямо а через цепочку рапределния обязанностей.

. В нем нет автовывода

Автовывода чего? Вскод умеет делать инференцию.

а вместо него все много раз дублируется и захламляет код

да нет же

я и захламляет код, снижая его читаемость и понятность.

Т.е. вот эта бестиповая каша в которой нужно все инварианты в глове держать «типа проще».

Тайпскрипт некоторые идеи передаст в js и отомрет

я не думаю что продукт от майков так легко сдастся.

Нет четкой спецификации синтаксиса языка

Есть, прямо в чейнджлоге.

язык состоит из отдельных фич, которые можно включить и выключить в конфиге.

Это называется «модульность» и вообще считается за добродетель.

Тестирование решает те же проблемы

Тесты показывают что баг есть, типы показывают что определённого бага нет в коде при условии соблюдения инвариантов в рантайме. Проблемы разные.

но делает это надежнее, потому, что проверяет не только сигнатуры, но и сложное поведение, в том числе асинхронное.

Тесты не проверяют что «всё работает правильно». Тесты проверяют что есть сабсет данных на которых имплементации работают правильно. Типы тоже умеют проверять «сложное поведение». Чекеры типа Z3 умеют проверять сложное поведение, тесты-нет. Но такие штуки ещё более сложны в использовании потому что не интегрированы в язык.

Ну и как показал уже Илья в докладах — это экономически не выгодно. Деньги потраченные на юниттесты дают лучший результат.

А почему тогда процессороделы не против вкинуть многобабок в верификацию теми же типами? «с жиру бесятся»?

В нем нет автовывода

ээээ? разве речь не о Type Inference?

3. ....Разработчики находятся под гипнозом ложной надежности и они меньше заботятся о тестах и ревью кода.
9. Тестирование решает те же проблемы, но делает это надежнее, потому, что проверяет не только сигнатуры, но и сложное поведение, в том числе асинхронное.

Надеюсь, вы там из тех же соображений линтер не выкинули.

Долго думал стоит что отвечать и стоит ли вообще, но раз Вы сами вышли в публичную плоскость, то извольте.

Ваш комментарий — почти полностью несостоятельны и вот почему:

1. TS позволяет включать JS и имеет тип any, что позволяет ему компилировать любой JS. Если у Вас есть доказательства обратного — будьте добры представить источник.
2. Баги есть везде, в том числе в рантайме. Это не аргумент что бы отказываться от инструмента (пока кол-во багов не превышает некую разумную границу).
3. Типы не изобретение TS-а. На Java/C#/Haskell написаны приложения ентерпрайз уровня. Гипноз их не убил.
4. В JS все равно нужно валидировать данные на границе приложения или между слоями. TS добавляет тут никакого оверхеда.
5. Какая разница о чем говорят разработчики в курилках? Если они говорят о проекте — уже хорошо. И как раз обсуждение типов дает возможность чуть дольше подумать об архитектуре, вместо того что бы сразу писать код.
6. Какой-то есть, хотя и не настолько сильный как в том же F#. По-поводу дублирования — будьте любезны предоставить пример, потому что в моем мире возможность посмотреть типы только упрощает читабельность.
7. Риски есть. Но TS это OpenSource под Apache License 2.0. Так что в случае чего его или подхватит сообщество, или напишут мигратор.
8. Единственный пункт с которым могу согласиться и то только в части отсутствия спецификации. Модульность это плюс, а не минус.
9. Тестирование не упрощает DX. Тесты не добавляют читабельности кода. Тесты сложнее поддерживать. TS не отменяет тестирования.
10. Тесты и TS ортгональнны. Вы можете иметь лучшее из двух миров.

Напиши мне на TS класс, который можно инстанциировать так: const connection = await new Connection(host, port); Все, о чем я написал гуглится и доказывается, но сделают это люди самостоятельно.

Э нет, Тимур, так не пойдет. Бремя доказывания лежит на утверждающем. Я нашел время ответить на все твои тезисы — будь любезен и ты, потом продолжим.
П.С. async factory и будет счастье.

Какая фабрика? Можно полностью на ФП пепейти, и что? В JS можно вернуть промис из конструктора, в TS нет — все, уже не все типизируется.

Вот такая например:

async function asyncFactory(): Promise<Connection> {
    const port = await Promise.resolve(8080);
    const host = await Promise.resolve('localhost');
    return new Connection(host, port);
}
Вам шашечки или ехать?
И что с остальным?

Мне шашички. TS не типизирует все конструкции JS, это факт. Заменять можно, но это уже не суперсет языка обещанный.

А никто не обещал что он будет выводить типы из всего что ты на JS напишешь. Даже после использования any (а это на секундочку встроенная функциональность) вся типизация летит к черту на рога. Но выполнить он выполнит.

Обещали не выводить типы, а не давать ошибку компилятора. Официальный слоган языка — TypeScript is a superset of JavaScript that compiles to clean JavaScript output — и с первого дня во всех презентациях на это давили — github.com/microsoft/TypeScript

const ShemsedinovConnection = function (host: string, port: number) { 
  return Promise.resolve({ host, port, comment: 'Nakhuya?' }) 
} as {} as { new(host: string, port: number): Promise<{ host: string, port: number }> } 
 
async function main() { 
  const connection = await new ShemsedinovConnection('host', 123); 
 
  console.log(connection); 
} 
Обещали не выводить типы, а не давать ошибку компилятора.

Вот простейший валидный JS:

let i = 1;
i = `Type 'string' is not assignable to type 'number'.`;

Код абсолютно валиден с точки зрения JS-а, но ошибка компилятора есть — и это правильно. Так что TS в принципе не может пропускать весь валидный JS.

Конструктор в нормальній архітектурі має повертати інстанс, а не казна-що, як вміє ваніла джс. Це також момент типізації

в нормальній архітектурі

ви маєте на увазі — ортодоксальній, аля «ранішній фаулер» :)

бо та архитектура добра — яка зрозуміла, щоб будувати своє — у тому ж стилі, і це не було боляче.

Це також момент типізації

типізація заради типизації — то звичайний догматизм

а поширення пітона, пихи та джс на бекенді (на фронті — браузери нав’язали), та й рубі — вказує що типизація не є обов’язковою для — успіху проекту.

Что хорошо и что плохо мы тут не обсуждаем. По спеке js поддерживает возврат промиса из конструктора, ts не поддерживает, но ts заявляет, что поддерживает типизацию любых конструкций js, т.е. официальный слонан — TypeScript is a superset of JavaScript that compiles to clean JavaScript output — github.com/microsoft/TypeScript

але по спеці він це не підтримує. це недокументована фіча, яка поки що існує, але в якихось нових реалізаціях es теж може не працювати

Поддерживает.

const ShemsedinovConnection = function (host: string, port: number) { 
  return Promise.resolve({ host, port, comment: 'Nakhuya?' }) 
} as {} as { new(host: string, port: number): Promise<{ host: string, port: number }> } 
 
async function main() { 
  const connection = await new ShemsedinovConnection('host', 123); 
 
  console.log(connection); 
} 

Это не класс с асинхронным конструктором,

connection.constructor.name

будет что? — Object

И че? JS

class X {
    async constructor() {} 
}
VM110:2 Uncaught SyntaxError: Class constructor may not be an async method
Надеюсь Вы не говорите своим студентам что нельзя использовать TS потому что он не поддерживает асинхронные конструкторы? JS тоже не поддерживает.

В js можно из конструктора любое че-хоч вернуть constructor() { return new Proise(r => ’и че?’); }, а если серьезно:
www.youtube.com/watch?v=dJr5Z2-QsfY

В ts тоже можно из конструктора любое че-хоч вернуть. Только зачем?

будет что? — Object

в js тоже будет обжект

return new Proise(r => ’и че?’);

у Вас вызов `r` потерялся.

const X = class X {
  constructor() {
    return new Promise(r => r('и че?'));
  }
} as { new(): Promise<string> }

async function main() {
  const v = await new X()
  console.log(v.length);
}

main()
Компилируется и выполняется. И знает что у v тип string.

Но этот хак можно развить... )))

UPD — вопрос на самом деле стоял о возможности вернуть промис из конструктора, так что этот ответ не релевантен

хах, тут якраз приклад того, чого не потрібно робити

почему?

Тому що new це ініціалізація об’єкта, які тут можуть бути відкладені виклики? Хоча звичайно можно будь-яку програму написати в одній функції makeGood() {...}
:)

Мы про спеку языка, спека говорит как можно, а не как нужно, и спека должна выполняться, даже если это ведет к говнокоду

Пожалуйста, приведите ссылку на стандарт ES, где прямым текстом разрешается возвращать промисы из конструктора.

А без TypeScript куда денется зацепление типов?

Как написать кусок нечитаемого говна для реализации простейшего функционала...

Ну, для найпростішого функціонала використовуйте JS, а для чогось складнішого — TS.

Хоча складні TypeScript-типи справді часто погано читаються, але на чистому JavaScript в таких випадках взагалі мало що можна буде зрозуміти, і прийдеться перечитувати самостійно код...

З іншого боку, якщо скрипт простий, то навряд чи анотації TypeScript будуть нечитабельними.

Так и не пишите это для простейшего функционала. Пишите там где это нужно и принесет пользу. Плюс TS-а в том что его можно использовать и просто, и сложно. Все зависит от ваших нужд.
Хаскель тоже сложно читается и тем не менее работает и поддерживается.

Хаскель читається дуже просто.

Якщо прочитати кілька коротких статей.

Наприклад, оцю

www.haskellforall.com/...​desugar-haskell-code.html

А можна українську версію?

Якщо DOU дозволить викласти переклад то з моєї сторони заперечень не буде.

Підписатись на коментарі