Как стать автором
Обновить

Комментарии 41

Все это замечательно, но будет ли дальнейшее развитие и пооддержка TypeScript майкрософтом,
при уже рабочем Blazor? Будут ли живы обе технологии или что то одно они похоронят?
Для чего будет нужен TypeScript, если теперь можно будет на C# под браузер писать?

TypeScript и Blazor/C# — слишком разные технологии, поэтому их сложно назвать конкурентами. Оба инструмента будут и дальше развиваться в своих нишах.

Разные то они разные, но в итоге решают одну и ту же задачу. Разве нет?

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

Да, но при этом одни языки «взлетают», а другие забрасывают.
Как пример — Ruby в 2007 и Ruby в 2020. Очем я и спрашивал.

В моем понимании вещей, вероятность быть заброшенным куда выше у Blazor, нежели у Typescript.

Забросят его, конечно, вряд ли, но до "джаваскрипту капец", который предрекает DarthWazer еще ооочень далеко

Я застал предыдущую попытку завоевать веб с помощью C# — она называлась Silverlight. Как-то не взлетело.


Субъективно вижу только два кейса, на которых Blazor бы блистал:


  1. Перевод в веб легаси-кода на C#, который страшно или слишком дорого переписывать
  2. Написание веб-приложений новичками, которые знают только C# и хотят использовать его как серебряную пулю для решения абсолютно любых задач

Обе этих ниши довольно узкие, поэтому существование Blazor как таковое представляется скорее как попытка MS впрыгнуть в уезжающий поезд хайпа вокруг WASM. А хайп — штука довольно эфемерная.

Спасибо за конкретный ответ, это я и хотел получить на свой первый коментарий.
Я только сейчас начал интересоваться TypeScript, вот это меня и беспокоит.
Blazor подходит только для тех кто хорошо знает C# большая часть фронтов которая не знает C# ради одной только типизации его учить не будет ( они скорее на Flow уйдут ). Typescript это по факту тот же js но с типами.

У многих языков есть возможность компилится в js тот же Dart, Scala, Kotlin и т.д и все это было задолго до Blazor. Как мы можем видеть до сих пор ничего из этого не взлетело. Так что я думаю что Blazor если и будет использоваться то только в стане C#, массовым он точно не станет.
Blazor/C# — платформа, упрощающая разработку фронтенда, разработчикам бэкэнда. Все это напоминает разработку мобильного приложения: писать нативно или гибридный вариант. Часть ниши закроет, но скорее небольшую. Typescript актуален пока актуален js
Это обеспечит типобезопасную работу со списком аргументов.

Насчёт типобезопасности, мы до сих пор можем написать так:


const album = findSongAlbum('taylor swift', 'bad blood')

Конкретно в этом примере такое вряд ли произойдёт, но возникают ситуации когда хочется себя дополнительно обезопасить и определить типы SongTitle, ArtistName. В TS это можно сделать с помощью костылей вроде type branding, но в язык nominal typing добавлять пока не спешат.


А так хочется сказать: "В TypeScript X.Y наконец появилось то, чего я очень ждал" =)

И? Эти аргументы ничего не сломают, просто не будет найден альбом.

А вообще да, номинальных типов, а также типов-подмножеств (только отрицательные/положительные, числа до 100, строки длиной (до) х символов) в определенных задачах не хватает, очень. Но спасибо и за то что есть. В крайнем случае, если уж очень нужно можно делать типы-обертки.

Программа работает неверно — это "ничего не сломают"?)

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

Никакая типизация не гарантирует, что программа будет работать верно.

Чего вам особенно не хватает в TypeScript?

Иногда очень сильно нехватает второго дженерик параметра у Promise, обозначающего тип ошибки.

на самом деле ошибку невозможно типизировать. представьте http запрос с json ответом. вы можете получить ошибку с сетью, а можете получить ошибку того что пришел не json и распарсить результаты не вышло. в этих случаях вы получите разные ошибки. по хорошему нужно чтобы все ошибки в catch блоках были типа unknown как это (опционально) предложили делать в конструкции try-catch, что будет семантически правильно. но в целом достаточно .catch(err: Error) писать


поэтому eslint например требует что если используется явно Promise.reject(err) то err должно быть что-то Error-подобное.

А это не самообман? Я имею ввиду, что он отнюдь неспроста там any (хотя имхо могли бы и unknown сделать). Никто не гарантирует, что Promise упадёт именно с таким типом, который вы желаете увидеть.

да, я совсем не спорю, что в Promise.reject можно засунуть все что угодно. и поэтому привел пример, что в eslint есть правило, которое разрешает использовать Promise.reject только с объектами типа Error и производных (что для меня кажется очень правильным)


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


я в домашних проектах всегда включаю strict: true, так что буду рад такой опции

Дык мой комментарий был ответом на сообщение от FODD :)

Так ничего не мешает сделать стандартную сигнатуру Promise<T, E=any>, чтобы программист переопределял её на свой страх и риск. В 99% случаев ничего не поменяется, зато в 1% я буду гарантированно знать, какого типа у меня будет ошибка.

Не хочу плодить веткок, ответ для n-srg
Для примеров с запросами: у нас же все-равно есть какой-нибудь класс-прослойка между приложением и библиотекой для запросов. Можно обрабатывать ошибки там и приводить к нужному виду. Даже если будет несколько типов ошибок через |, ничего нам не помешает обработать их через type-guards.

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

зато в 1% я буду гарантированно знать, какого типа у меня будет ошибка.

Повторюсь, по моему мнению, вы занимаетесь самообманом. Видимо вы устали писать код вида:


.catch(error => {
  if (isBlaBlaError(error)) 
    handleBlablaError(error);
  else
    handleUnknownError(error);
});

Предполагая, что handleUnknownError чрезвычайно маловероятен. И желаете писать код вида:


.catch(handleBlaBlaError)

Всё так? Если да, то не проще ли сделать так:


.catch(genErrorHandler(blaBlaErrorPair))

Где blaBlaErrorPair это комбо { guard: isBlaBlaError, handler: blaBlaErrorHandler }? И волки сыты, о овцы целы. На мой взгляд желая Promise<Result, Error> вы желаете странного :)

В TS4 хотя бы дали возможность типизировать как unknown

В catch может прилететь, все, что только возможно, любое исключение попадет в этот блок. Посмотрите в сторону монады either, она поможет разделить исключения и ошибки.

Чего не хватает, чего не хватает… очевидного не хватает — например, нормальной поддержки ООП для статических свойств/методов (abstract static не работает и protected static тоже; typeof MyClass нельзя; typeof this.constructor = Function, а не тип своего класса, и т.д.). Там много issues подобного рода висит открытыми годами.

например, нормальной поддержки ООП для статических свойств/методов (abstract static не работает и protected static тоже

А где abstract static работает? Во многих языках он не возможен — Java, C#, в php раньше можно было, потом запретили.


protected static работает в TS, например:


class Logger {
    ['constructor']: typeof Logger
    protected static PREFIX = '[info]'
    public log(message: string): void {
        console.log(this.constructor.PREFIX + ' ' + message)
    }
}

class Warner extends Logger {
  protected static PREFIX = '[warn]'
}

const a = new Logger(); a.log('a')
const b = new Warner(); b.log('b')

Про "typeof MyClass нельзя" я не понял.

Я так понимаю, речь идет о конструкции вроде


function createInstance(classConstructor: typeof MyClass): MyClass {
  return new classConstructor('some arg');
}

Сейчас можно только classConstructor: { new(someArg: string) => MyClass }

Работает же и так:


class MyClass {
  constructor(arg: string) {
    console.log(arg)
  }
}

function createInstance(classConstructor: typeof MyClass): MyClass {
  return new classConstructor('some arg')
}

createInstance(MyClass)

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

А что мешало IDE совместить имена параметров из функции и типы из описания типов? Они ж в одном порядке идут. Вернее шли до 4.0, сейчас, вероятно, можно перемешивать.
Я не знаю не js ни ts. Скажите, а это такое странное описание функций там? Почему так сделали?
type Params: [title: string, artist: string]
const findSongAlbum: IQuery<Album, Params> = (title, artist) => {


Чем оно удобнее того же питона/с/java/go?
IQuery<Album> findSongAlbum(string title, string artist) {
...
Вы все напутали.

В приведенном вами примере ваш код утверждает, что функция findSongAlbum вернет тип IQuery

НО, в примере из статьи, декларируется что переменная findSongAlbum имеет тип IQuery. Этот тип, судя по всему является вызываемым (callable), проще говоря это тип-функция. Затем мы присваиваем этой переменной анонимную функцию, и поскольку ее тип уже известен, нет нужды проставлять типы параметров.
Когда определяешь сам метод то да, ваш вариант удобнее. И он точно также выглядит в ts. Но допустим функция должна принимать другую функцию, определенного типа. Тогда Параметр надо как-то объявить.
Точно на TS пишете? ) Если функция принимает другую, определенного типа, то в чем проблема обьявить параметр во втором примере кода, если бы он был TypeScript'ом?

function findSongAlbum(finder: (songs: Song[]) => Song) { //...
Если у вас 10 таких методов, которые получают однотипную функцию? В каждом будете объявление делать? Я не говорю что нельзя так делать, есть дженерики в конце концов. Но есть разница — каждый раз описывать сигнатуру функции, захламляя код или объявить в декларативном стиле.
А кажись понял, это как на том же с++ определить переменную типа функция и присвоить ей лямбду.
Это лямбда (title, artist) => {}, назначенная в переменную findSongAlbum, т.к. js язык с first-class functions.
Более традиционный синтаксис тоже есть:
function findSongAlbum(title: string,  artist: string): IQuery<Album> {

}
не хватает pattern matching'a и вспомогательного типа Option
Зарегистрируйтесь на Хабре, чтобы оставить комментарий