6:45 это очень спорное утверждение в отношении того, когда и что использовать. Интерфейсы и типы во многом взаимозаменяемы. Как следует из двух важных отличий интерфейсов от типов, а именно: не возможность расширить интерфес от union-типа, и невозможность расширить декларацию типа, то интерфейс надо использовать, когда потребуется по-разному расширять его декларацию (например, на бэке и на фронте setTimeout имеет разныую сигнатуру), а типы надо использовать, когда требуется создание union типов. Конечно, нужно учесть, что интерфейсы являются более привычными для сторонников классического (JAVA-подобного) ООП, и собственно, невозможность наследования от union типа обусловленна именно этим фактом. У нас на проектах: типы -- для анимичных моделей, интерфейсы -- для описания поведения. Фактически получается, что все доменные объекты описаны типами, а все сервисы описаны интерфейсами. у объектов нет методов, есть только поля, а у сервисов нет полей, только -- методы. Но, это все не более, чем соглашение одной команды для определенной группы проектов. В подавляющем большинстве случаев стоит выбрать тот инструмент, который более удобен (привычен) для вашей команды.
Когда пользуешься типами на уровне A: string,, B: number, то от скуки возникает странное желение начинать спорить где и что лучше использовать... Когда пишешь свои универсальные типы на дженериках, то такой вопрос не стоит)
@@Mr.Bellamy ну, якщо сперичатися про програмування, то від нудьги, то сперичатися про сперічання, то, мабудь, від дуже великої нудьги ;) Я, наприелад, цілеом погоджуюся з Вашим висловом: "Говорю, как использую сам. Это не значит, что все должны писать так же". Шкода, що цього уточнення не має у відео, і шкода, що я з легкістю можу отримати посилання на це відео, як аргумент на використання синтаксісу інтерфейса для анемічної моделі. От і все.
мне кажется там все предельно понятно, если ты понимаешь концепцию интерфейса. а type им следовало назвать alias и тогда бы точно не было бы никаких путаниц
Кортеж нельзя опиcать интерфейсом. В этой реализации можно деструктеризировать любое количество ствойств, и все они будут any. Что значит вы типизировали не кортеж, а 2 первых элемента массива. const [value, effect, a, b, c] = state; TypeScript не будет ругаться на такую запись.
@@wisejs Да, строго говоря, это действительно не кортеж. Это массив с по-разному типизированными элементами. И да, если так наследоваться, то лучше от Array. Немного безопаснее.
Пардон, но я что-то не догнал вашего утверждения о том что длинна кортежа не меняется,. Почему тогда основываясь на вашем примере могу пушить данные в переменную с типом State и длинна массива меняется?
3:40 NamesA и NamesB разные декларации. NamesB является аналогом вот такой: type NameC = { [idx: number]: string } У обоих деклараций, и NamesB и NamesC будут отсуствовать методы массива. const b: NamesB = ['a', 'b', 'c']; b.length -- выдасть ошибку "length" is not present in NamesB Аналогом NamesA будет: interface NamesD extends Array {};
@@wisejs NamesC тоже тип. И опять же, смотря что надо описать. Может так и надо сделать, чтобы не было методов массива и читать надо было по прямому индексу. Кстати, как параметр функции вполне подойдет
2:02 надо еще SumC добавить. Аналог SumA. type SumС = { (a: number, b: number): number; } const sum: SumC = (a, b) => a + b; Здесь надо сказать, что SumA и SumC нужны когда для функии задаются дополнительные свойства (как, например, в случае с express), в остальных случаях функцию лучше тайпать, как SumB -- проще читается.
Было бы интересно про перегрузку послушать тк на практике не приходилось использовать, соответственно полного понимания непосредственно, зачем реализована такая возможность нет. Буду благодарен за пример из жизни, а не на "котиках")))
В видео очень много ошибок и неточностей 3:42 NameA и NameB не идентичные типы, тут записть NameA эквивалентна типу Array, в то время как NameB это Record. Первое - массив строк, второе - объект с ключами типа number и значениями типа string, во втором случае отсутствуют поля и методы массива как length, push, pop и так далее 5:16 const obj: C = .... в этом случае поля age и name разрешены не потому что тип C объявлен как A | B, а потому что из-за структурной типизиции к объекту типа C можно добавить любое поле и он все еще будет иметь тип C. Сам тип A | B описывает либо поле name, либо age, но не два сразу. Для этог онужно использовать запись A & B
вы вроде не сказали в ролике главного отличия, как написано в документации, что type cannot be re-opened to add new properties vs an interface which is always extendable
Как динамически менять дженерик тип. Есть функция которая отрабатывает и получает DataCode от 1 - 11 . Нужно как то организова такой функционал. type AllKey = "A" | "B" | "C".... I_Test interface I_Test { name: string; item: Array ; }
@@wisejs Как в разный момент времени подкидывать в let a:I_Test = {name: "Вася", items: [{model: "BMW"}] let a:I_Test = {name: "Петя", items: [{cityl: "Moscow"}] let a:I_Test = {name: "Борис", items: [{prof: "Повар-тракторист"}] и т. д. В функции в которой переменная "a" меняеться приходит так же при разном вызове одно из чисел от 1-11. типов так же от 1-11 существует мне как то надо их подкидывать ориентируясь на число
Вопрос по теме union, есть ли в ts возможность описать, например тип С, так, чтобы он принимал либо только свойство из типа А, либо только свойство из типа В?
Вроде как в самом ts нет встроенного утильного типа, но в целом это называется mutually exclusive types или XOR, на стэковерфлоу есть реализация, гугл выдаёт первой ссылкой
Спасибо за видео. А нету у Вас случайно в планах записать видео по правильному подключению роутов, если есть как публичные роуты так и приватные. В интернете есть разная информация: кто-то создает 2 объекта: publicRoutes и privateRoutes, в другом способе объект единый, но компонент делают свой - кастомный роут - privateRoute. И как правильно построить структуру, если например есть не только user и admin, а, допустим 3 уровня доступа, user; moderator; admin; Про то, как правильно организовать все в таком случае информации вообще нету. Спасибо
У меня как то был косяк с аргументами функции При такой записи: const getTableRows = (someArg: ISomeArg[], columns: ITypeA[] | ITypeB[]) => .... тайп скрипт ругался на: This expression is not callable. Я заменил это на const getTableRows = (someArg: ISomeArg[], columns: C[]) => .... и лыжи поехали. Это какой то Юнион тайп из мира интерфейса получился что ли? P.S В итоге всё равно пришлось переделать , а то выглядело не оч))
Можно было написать проще, с тем же результатом: `const getTableRows = (someArg: ISomeArg[], columns: (ITypeA | ITypeB)[]) => ...` С т.з. типобезопасности, `Array | Array` - это не то же самое, что `Array`. Но вот то, что переменная с типом `const arr: Array | Array` создаёт больше проблем, чем пользы - это реально вымораживает, даже если ITypeA и ITypeB структурно идентичны. В итоге приходится идти на компромисс (это ж ts, как тут без компромиссов) и менять тип на `const arr: Array` и тогда "лыжи начинают ехать"
@@denisdragomirik golang или любой строго типизированный язык программирования тебе в помощь, чтобы разобраться в разнице между типом и интерфейсом. Даже всеми ненавидимый php с динамической типизацией знает что есть тип, а что есть интерфейс, и только нубы от тайпскрипта никак её не поймут.
@@kdnlinker а ти уяви, що в тебе не властивість, а геттер. А геттер - це метод. Якщо не згоден - вчи основи TypeScript. У C#, до речі, подібна концепція
@@denisdragomirik ghbx`v pltcm ctnnth b utnnth? ns rjulf yf [j[kzwrjv dtoftim? nj dtofq d cdjtq [j[kj;jgbb/ Включишь русскую раскладку и прочитаешь, а как у Зели спросишь.
Автор видео не понял смыслового различия между Interface и Type. В офф документации TypeScript, других С-подобных языках и книгах по ОПП есть чёткое описание предназначения. Для тех кто хочет это действительно понять, обратитесь к этой литературе.
За что же JavaScript`у так не повезло?! TypeScript это - самая уродливая разработка которую я видел за 33 года работы программистом. Создавая его авторы не имели конкретной цели - внесли кучу путаницы, так и не делегировав относительность и приоритеты типов и интерфейсов. По всей видимости и сейчас не могут. Что мешало сделать интерпретатор с (например) Java или C# через WebAssembly - в JavaScript? Как я люблю Web разработку и как я устал от постоянной костылизации решений. Создание интерпретатора - не тривиальная задача! Но ...чего не хватает в мире JavaScript разработки так это - архитекторов!
@@konstantinov_it Я думаю может просто не нужно его воспринимать так серьезно - как язык программирования. Он как был - script, так и остался - скриптом. В этом его прелесть. Да и javascript - не панацея, а одно из решений для web задач. Можно писать Web не только на JavaScript`е. Просто что последнее - менее популярное решение.
@@ugin-nb4syХах, ты какие-то курсы проходил? "Как поверить в себя за 15 дней" ? Малыш )) Откуда ты такой мотивированный? ))) Видно что ты еще - зеленый как трава ))) Твои розовые рассуждения выдают твой возраст, сын )
@@ugin-nb4syА шо ты такое вообще? AI который поверил в себя? Сын, мне вообще твое мнение - ...по барабану (мягко сказано). Мои скилы еще какой-то "июнь" не проверял 😀 Я плачу от такого расклада ))) Ты мне начинаешь нравится - ты смешной! 😀Может к тебе еще на курсы записаться? 😀😀😀😀😀
офигительная лекция. Просто супер. Процветания тебе, Автор!
6:45 это очень спорное утверждение в отношении того, когда и что использовать. Интерфейсы и типы во многом взаимозаменяемы. Как следует из двух важных отличий интерфейсов от типов, а именно: не возможность расширить интерфес от union-типа, и невозможность расширить декларацию типа, то интерфейс надо использовать, когда потребуется по-разному расширять его декларацию (например, на бэке и на фронте setTimeout имеет разныую сигнатуру), а типы надо использовать, когда требуется создание union типов.
Конечно, нужно учесть, что интерфейсы являются более привычными для сторонников классического (JAVA-подобного) ООП, и собственно, невозможность наследования от union типа обусловленна именно этим фактом.
У нас на проектах: типы -- для анимичных моделей, интерфейсы -- для описания поведения. Фактически получается, что все доменные объекты описаны типами, а все сервисы описаны интерфейсами. у объектов нет методов, есть только поля, а у сервисов нет полей, только -- методы. Но, это все не более, чем соглашение одной команды для определенной группы проектов.
В подавляющем большинстве случаев стоит выбрать тот инструмент, который более удобен (привычен) для вашей команды.
Говорю, как использую сам. Это не значит что все должны писать так же.
Мы тоже в команде придерживаемся подобного подхода.
Когда пользуешься типами на уровне A: string,, B: number, то от скуки возникает странное желение начинать спорить где и что лучше использовать...
Когда пишешь свои универсальные типы на дженериках, то такой вопрос не стоит)
@@Mr.Bellamy ну, якщо сперичатися про програмування, то від нудьги, то сперичатися про сперічання, то, мабудь, від дуже великої нудьги ;)
Я, наприелад, цілеом погоджуюся з Вашим висловом:
"Говорю, как использую сам. Это не значит, что все должны писать так же".
Шкода, що цього уточнення не має у відео, і шкода, що я з легкістю можу отримати посилання на це відео, як аргумент на використання синтаксісу інтерфейса для анемічної моделі.
От і все.
Когда смотрю такие видео - понимаю, как мало я знаю... Спасибо за видео
Прям ваще годное видео - чётко, сжато, конкретно и по делу! Однозначно Like 👍
Круто объяснил! Спасибо огромное, все понятно, крутые примеры!
0:25 для этих целей так же можно использовать и class и typeof любього объекта (но это считай будет type, только без присвоенного типа)
Спасибо что продолжаете радовать нас отличным контентом!
Хорошее видео! Четко и без воды
Спасибо! Много новых тонкостей узнал.
Очень доходчиво объяснил про разницу Type и Interface в Typescript
Спасибо за ключевые слова))
Респект за сохраненное время!
Какие темы по TypeScript раскрывать в следующих видео?
Generic и когда их стоит использовать.
Mixins, особенно как юзать в ангуляре
Женерики
Спасибо друг за твою работу...
спасибо, кратко, толково, без воды. случайно попал сюда, подписался
спасибо, сюда попали все случайно, но остаются не случайно😉
Урок очень хороший много понятно стало
Очень хороший урок. Большой молодец👍, ждем продолжения
Все четко и по делу!👍🏻👍🏻👍🏻
Полезно, спасибо
мне кажется там все предельно понятно, если ты понимаешь концепцию интерфейса.
а type им следовало назвать alias и тогда бы точно не было бы никаких путаниц
Огонь, спасибо, больше ТС в ньюансах!
Хорошее видео, спасибо!
Спасибо, очень полезно!
Хороший урок.
Есть еще интересная тема - типы событий. Где и какие типы указывать, неясно.
Еще интересная тема - ответ от сервера. Какие типы указать
Спс за годный контент, а то я в ts недавно, многих вещей ещё не знаю
Хороший урок, спасибо за труд!
Хороший урок. Но по поводу последнего, то это субъективно. Так как это уже больше принимается на уровне команды и по сути отличий у них почти нет
Согласен. Это правило, которое использую я.
Привет всем, не могли бы подсказать, какой тип 'file' будет в реакте?
Гооодно!!! 🙏🏻💪🏻
Покажите как типизировать API и функции высшего порядка. Годного материала не могу найти. Спасибо.
риал
дженерики в помощь
Он значительно лучше express и если вам нужна типизация, а для разработки хороших АПИ, она вам нужна, то это идеальный вариант
Спасибо! хороший урок!
3:52 - Кортеж можно описать интерфейсом. Правда, это будет выглядеть несколько громоздко и непривычно, но это возможно:
interface IState extends Array {
[0]: number;
[1]: (n: number) => void;
length: 2;
}
const state: IState = [10, (n) => console.log(10 + n)];
const [value, effect] = state;
Кортеж нельзя опиcать интерфейсом.
В этой реализации можно деструктеризировать любое количество ствойств, и все они будут any. Что значит вы типизировали не кортеж, а 2 первых элемента массива.
const [value, effect, a, b, c] = state;
TypeScript не будет ругаться на такую запись.
@@wisejs
Да, строго говоря, это действительно не кортеж.
Это массив с по-разному типизированными элементами.
И да, если так наследоваться, то лучше от Array.
Немного безопаснее.
3:47
Вторая запись не предлагает наличие методов массива в экземпляре
Пардон, но я что-то не догнал вашего утверждения о том что длинна кортежа не меняется,. Почему тогда основываясь на вашем примере могу пушить данные в переменную с типом State и длинна массива меняется?
Отличное описание нюансов, краткое и ёмкое, спасибо
Спасибо за комментарий!
Хотелось бы хорошо разобраться с декораторами.
у меня в редакс тулките store ругается на этот интерфейс, переименовал в type и теперь норм. Не пойму в чем дело
3:40 NamesA и NamesB разные декларации. NamesB является аналогом вот такой:
type NameC = { [idx: number]: string }
У обоих деклараций, и NamesB и NamesC будут отсуствовать методы массива.
const b: NamesB = ['a', 'b', 'c'];
b.length -- выдасть ошибку "length" is not present in NamesB
Аналогом NamesA будет:
interface NamesD extends Array {};
Тут нужно отдавать приоритет типам.
@@wisejs NamesC тоже тип.
И опять же, смотря что надо описать.
Может так и надо сделать, чтобы не было методов массива и читать надо было по прямому индексу.
Кстати, как параметр функции вполне подойдет
TypeScript и Saga
2:02 надо еще SumC добавить. Аналог SumA.
type SumС = {
(a: number, b: number): number;
}
const sum: SumC = (a, b) => a + b;
Здесь надо сказать, что SumA и SumC нужны когда для функии задаются дополнительные свойства (как, например, в случае с express), в остальных случаях функцию лучше тайпать, как SumB -- проще читается.
Да, верно. Второй ваш коммент UA-cam забанил, не могу его прочесть и ответить.
о каких дополнительных свойствах идет речь? SumA.propertie = 123 ?
разобрался, верно
Было бы интересно про перегрузку послушать тк на практике не приходилось использовать, соответственно полного понимания непосредственно, зачем реализована такая возможность нет. Буду благодарен за пример из жизни, а не на "котиках")))
Сделаю про перегрузку.
@@wisejs спасибо, жду с не терпением
В видео очень много ошибок и неточностей
3:42
NameA и NameB не идентичные типы, тут записть NameA эквивалентна типу Array, в то время как NameB это Record. Первое - массив строк, второе - объект с ключами типа number и значениями типа string, во втором случае отсутствуют поля и методы массива как length, push, pop и так далее
5:16
const obj: C = .... в этом случае поля age и name разрешены не потому что тип C объявлен как A | B, а потому что из-за структурной типизиции к объекту типа C можно добавить любое поле и он все еще будет иметь тип C. Сам тип A | B описывает либо поле name, либо age, но не два сразу. Для этог онужно использовать запись A & B
именно так и подумал когда смотрел видео. хорошо что Вы это выразили текстом.
Привет всем, не могли бы подсказать, какой тип 'file' будет в реакте?
Интересно!
вы вроде не сказали в ролике главного отличия, как написано в документации, что type cannot be re-opened to add new properties vs an interface which is always extendable
разве этого не звучало может не дословно, но по смыслу так?
6:02
Хорошо осветил
Красавчик!
Как динамически менять дженерик тип. Есть функция которая отрабатывает и получает DataCode от 1 - 11 . Нужно как то организова такой функционал. type AllKey = "A" | "B" | "C".... I_Test interface I_Test { name: string; item: Array ; }
Ничего не понял.
@@wisejs Как в разный момент времени подкидывать в let a:I_Test = {name: "Вася", items: [{model: "BMW"}] let a:I_Test = {name: "Петя", items: [{cityl: "Moscow"}] let a:I_Test = {name: "Борис", items: [{prof: "Повар-тракторист"}] и т. д. В функции в которой переменная "a" меняеться приходит так же при разном вызове одно из чисел от 1-11. типов так же от 1-11 существует мне как то надо их подкидывать ориентируясь на число
Можете пример кода прикрепить с ошибкой?
Красава!
Это получается все что связано с Mapped types и Utility types лучше использовать в type?
лучше всего да, ибо через интерфейсы это как бы не получится)
Круто!
Все классно, но очень быстро, мало примеров
по-моему, достаточно)
Вопрос по теме union, есть ли в ts возможность описать, например тип С, так, чтобы он принимал либо только свойство из типа А, либо только свойство из типа В?
Вроде как в самом ts нет встроенного утильного типа, но в целом это называется mutually exclusive types или XOR, на стэковерфлоу есть реализация, гугл выдаёт первой ссылкой
Возможно Record
type xor = keyof A | keyof B;
расскажи про дженерики плз
Красвава!
Спасибо за видео. А нету у Вас случайно в планах записать видео по правильному подключению роутов, если есть как публичные роуты так и приватные. В интернете есть разная информация: кто-то создает 2 объекта: publicRoutes и privateRoutes, в другом способе объект единый, но компонент делают свой - кастомный роут - privateRoute. И как правильно построить структуру, если например есть не только user и admin, а, допустим 3 уровня доступа, user; moderator; admin; Про то, как правильно организовать все в таком случае информации вообще нету. Спасибо
Хорошая идея, запишу себе 😉
А скажи плиз свое мнение насчет типизации пропсов
Type vs Interface
Я юзаю просто React.FC
@@wisejs а если кол-во пропсов 10+
Чаще всего это значит что компонент делает слишком много всего, и нужно изменить апи)
не удаляй пока видос. я попозже посмотрю что ты там сделал.
Не планировал ))
У меня как то был косяк с аргументами функции
При такой записи:
const getTableRows = (someArg: ISomeArg[], columns: ITypeA[] | ITypeB[]) => ....
тайп скрипт ругался на: This expression is not callable.
Я заменил это на
const getTableRows = (someArg: ISomeArg[], columns: C[]) => ....
и лыжи поехали.
Это какой то Юнион тайп из мира интерфейса получился что ли?
P.S В итоге всё равно пришлось переделать , а то выглядело не оч))
А причем здесь интерфейс? Extends тут выполняет совсем другую роль. Он ограничивает тип, а не расширяет его.
Можно было написать проще, с тем же результатом:
`const getTableRows = (someArg: ISomeArg[], columns: (ITypeA | ITypeB)[]) => ...`
С т.з. типобезопасности, `Array | Array` - это не то же самое, что `Array`.
Но вот то, что переменная с типом `const arr: Array | Array` создаёт больше проблем, чем пользы - это реально вымораживает, даже если ITypeA и ITypeB структурно идентичны. В итоге приходится идти на компромисс (это ж ts, как тут без компромиссов) и менять тип на `const arr: Array` и тогда "лыжи начинают ехать"
Интерфейс должен определять методы, но никак не свойства, тогда сразу будет понимание разницы между типом и интерфейсом.
Удачи 😁
@@denisdragomirik golang или любой строго типизированный язык программирования тебе в помощь, чтобы разобраться в разнице между типом и интерфейсом. Даже всеми ненавидимый php с динамической типизацией знает что есть тип, а что есть интерфейс, и только нубы от тайпскрипта никак её не поймут.
@@kdnlinker а ти уяви, що в тебе не властивість, а геттер. А геттер - це метод. Якщо не згоден - вчи основи TypeScript. У C#, до речі, подібна концепція
@@denisdragomirik ghbx`v pltcm ctnnth b utnnth? ns rjulf yf [j[kzwrjv dtoftim? nj dtofq d cdjtq [j[kj;jgbb/ Включишь русскую раскладку и прочитаешь, а как у Зели спросишь.
@@kdnlinker Не збираюсь)
Интерфейс не попадает в компиляцию
Тип тоже. Тайпскрипт типы вообще не попадают в компиляцию.
Автор видео не понял смыслового различия между Interface и Type. В офф документации TypeScript, других С-подобных языках и книгах по ОПП есть чёткое описание предназначения. Для тех кто хочет это действительно понять, обратитесь к этой литературе.
в 2 словах? куда копать?
с учетом особенностей попробоавали везде использовать интерфейсы и только когда этого совсем нельзя, то типы и все нормально получается.
За что же JavaScript`у так не повезло?! TypeScript это - самая уродливая разработка которую я видел за 33 года работы программистом. Создавая его авторы не имели конкретной цели - внесли кучу путаницы, так и не делегировав относительность и приоритеты типов и интерфейсов. По всей видимости и сейчас не могут. Что мешало сделать интерпретатор с (например) Java или C# через WebAssembly - в JavaScript? Как я люблю Web разработку и как я устал от постоянной костылизации решений. Создание интерпретатора - не тривиальная задача! Но ...чего не хватает в мире JavaScript разработки так это - архитекторов!
Умом JS нам не понять,
Аршином общим не измерить:
У ней особенная стать -
В JS мы можем только верить.
@@konstantinov_it Я думаю может просто не нужно его воспринимать так серьезно - как язык программирования. Он как был - script, так и остался - скриптом. В этом его прелесть. Да и javascript - не панацея, а одно из решений для web задач. Можно писать Web не только на JavaScript`е. Просто что последнее - менее популярное решение.
@@ugin-nb4sy Через лет 5 Vaadin и TS будет чем-то вроде jQuery или Adobe Flash - что с этим делать? Ты будешь сопровождать это барахло? )))
@@ugin-nb4syХах, ты какие-то курсы проходил? "Как поверить в себя за 15 дней" ? Малыш )) Откуда ты такой мотивированный? ))) Видно что ты еще - зеленый как трава ))) Твои розовые рассуждения выдают твой возраст, сын )
@@ugin-nb4syА шо ты такое вообще? AI который поверил в себя? Сын, мне вообще твое мнение - ...по барабану (мягко сказано). Мои скилы еще какой-то "июнь" не проверял 😀 Я плачу от такого расклада ))) Ты мне начинаешь нравится - ты смешной! 😀Может к тебе еще на курсы записаться? 😀😀😀😀😀
Ещё нельзя наследовать классы от типов, только интерфейсы
Классы и от интерфейсов нельзя наследовать. Класс - это реализация интерфейса. A extends в интерфейсе работает с типом, что я и показываю в видео.
👉 Этот комментарий создан в качестве уважения автору и для продвижения его канала.
ответил с той же целью длинною более 4 слов, поскольку присутствует полезное содержимое.
@@romanmed9035 ну и я тогда поддержу, можно ещё политический срач развести, тогда комментариям не будет отбоя:)
@@user-Duke2017 ну срач наверное все же не надо. остановимся на приличном.
Урок сложный. Новичку непонятно
сайдет подписочка
Сложно
ua-cam.com/video/hGdx0hpZsvs/v-deo.html interface D {
name?:string;
age?:number;} интерфей так может