Mapped Types в TypeScript
Статья (англ.): https://javascript.plainenglish.io/using-typescript-mapped-types-like-a-pro-be10aef5511a
В статье очень подробно разбираются Mapped Types - такие типы, которые берут один тип с определенным набором полей и создают из него другой тип с таким же набором полей. При этом может изменяться типизация этих полей или их настройки (например, обязательность).
Например, если у нас есть тип:
то из него можно получить:
Это самый банальный пример, на самом деле там все намного интереснее.
К посту прилагается картинка, на которой изображено "внутреннее устройство" утилит
#typescript #подкапотом #ссылки
Статья (англ.): https://javascript.plainenglish.io/using-typescript-mapped-types-like-a-pro-be10aef5511a
В статье очень подробно разбираются Mapped Types - такие типы, которые берут один тип с определенным набором полей и создают из него другой тип с таким же набором полей. При этом может изменяться типизация этих полей или их настройки (например, обязательность).
Например, если у нас есть тип:
type User = {
name: string;
password: string;
address: string;
phone: string;
};
то из него можно получить:
type UserPartial = {
name?: string;
password?: string;
address?: string;
phone?: string;
};
Это самый банальный пример, на самом деле там все намного интереснее.
К посту прилагается картинка, на которой изображено "внутреннее устройство" утилит
Partial
, Required
, Readonly
и Pick
, которые в общем и являются Mapped Types. На первый взгляд выглядит страшно, но статья подробно объясняет, как это работает, и как самостоятельно создавать типы с похожей функциональностью. #typescript #подкапотом #ссылки
👍2🔥1
Своими словами:
в этих типах мы используем обобщения (дженерики).
Например, утилита
Она берет все ключи исходного типа (
Но к каждому полю добавлен значок
А типы полей ровно те же самые, что и у исходного типа -
В итоге получается точно такая же структура, но каждое поле в ней необязательное.
#typescript
в этих типах мы используем обобщения (дженерики).
Например, утилита
Partial
принимает некий тип T
, неизвестно, какой конкретно, и на его основе создает новый тип.Она берет все ключи исходного типа (
keyof T
) и делает их своими ключами. Каждый конкретный ключ обозначается типом P
. То есть P
- это каждый ключ типа T
, и у нового типа будут те же самые поля.Но к каждому полю добавлен значок
?
- то есть поле становится опциональным, необязательным.А типы полей ровно те же самые, что и у исходного типа -
T[P]
. Это обычный синтаксис доступа к свойствам объекта, но тут он применяется к типу.В итоге получается точно такая же структура, но каждое поле в ней необязательное.
#typescript
👍2🔥1
Typescript. Утилиты. Часть 2 (Exclude, Extract, NonNullable)
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Exclude
Принимает два параметра:
-
-
Результатом является объединение, в которое входят все члены
Extract
Принимает два параметра:
-
-
Результатом является объединение, в которое входят все члены
NonNullable
Принимает один параметр
#typescript
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Exclude
Принимает два параметра:
-
Union
-
ExcludedMembers
- члены, которые нужно исключить из Union
Результатом является объединение, в которое входят все члены
Union
, кроме тех, которые могут быть присвоены в ExcludedMembers
Extract
Принимает два параметра:
-
Type
-
Union
- объединение типов, которые нужно отобрать из Type
Результатом является объединение, в которое входят все члены
Type
, которые одновременно могут быть присвоены в Union
NonNullable
Принимает один параметр
Type
и выбрасывает из него null
и undefinded
.#typescript
👍2🔥1
Typescript. Утилиты. Часть 3 (Parameters, ReturnType)
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Утилиты
Возьмем функцию:
В утилиту нужно передать тип этой функции, а не ее значение:
Утилита
Утилита
#typescript
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Утилиты
Parameters
и ReturnType
работают с функциями и могут, соответственно, получать типы входных параметров или возвращаемого значения.Возьмем функцию:
function add(num1: number, num2: number): number {
return num1 + num2;
}
В утилиту нужно передать тип этой функции, а не ее значение:
typeof add
Утилита
Parameters
вернет кортеж их типов входных аргументов: [num1: number, num2: number]
Утилита
ReturnType
вернет тип возвращаемого значения:number
#typescript
👍3
TypeScript. Условные типы
Статья (англ): https://javascript.plainenglish.io/use-typescript-conditional-types-like-a-pro-7baea0ad05c5
Утилиты Exclude, Extract, NonNullable, Parameters, and ReturnType используют "условные типы" (Conditional Types).
В статье подробно разбирается их внутреннее устройство, разобравшись с которым можно создавать свои похожие утилиты.
Общий синтаксис условных типов выглядит так:
Берется некий тип
Простейшая утилита
Она просто определяет, является ли переданный тип строкой.
Но можно делать и намного более сложные вещи.
Распределенные условные типы
Если передать в утилиту объединение типов, на выходе тоже можно получить объединение, потому что операция выполняется для каждого члена объединения - это называется _распределенные условные типы__ (distributed conditional type).
Но это работает только для "голых" типов, не обернутых в массивы/кортежи/промисы.
#typescript #ссылки #подкапотом
Статья (англ): https://javascript.plainenglish.io/use-typescript-conditional-types-like-a-pro-7baea0ad05c5
Утилиты Exclude, Extract, NonNullable, Parameters, and ReturnType используют "условные типы" (Conditional Types).
В статье подробно разбирается их внутреннее устройство, разобравшись с которым можно создавать свои похожие утилиты.
Общий синтаксис условных типов выглядит так:
T extends U ? X : Y
Берется некий тип
T
и присваивается типу U
(проверяется, входит ли T
в U
). Если да, возвращается X
, если нет - Y
(X
и Y
могут быть чем угодно, например, тем же исходным типом T
).Простейшая утилита
IsString
такого рода может выглядеть так:T extends string ? true : false
Она просто определяет, является ли переданный тип строкой.
Но можно делать и намного более сложные вещи.
Распределенные условные типы
Если передать в утилиту объединение типов, на выходе тоже можно получить объединение, потому что операция выполняется для каждого члена объединения - это называется _распределенные условные типы__ (distributed conditional type).
Но это работает только для "голых" типов, не обернутых в массивы/кортежи/промисы.
#typescript #ссылки #подкапотом
👍4
TypeScript. Пересечения
Статья (англ.): https://javascript.plainenglish.io/using-typescript-intersection-types-like-a-pro-a55da6a6a5f7
Статья подробно рассказывает об операторе
Если он работает с примитивными значениями, то понять, каким будет результат просто - этот оператор работает как логическое И:
Если один из операндов
Если один из операндов
Если же операнды являются объектами, то оператор работает с каждым полем этих объектов.
Если есть одинаковые поля с конфликтующими типами, будет
В статье есть интересный пример использования пересечения для функций с разной сигнатурой - фактически перегрузка функций с разными наборами параметров.
А в заключение дается пример использования пересечения вместе с MappedTypes, над которым можно немного поломать голову.
#typescript #ссылки #подкапотом
Статья (англ.): https://javascript.plainenglish.io/using-typescript-intersection-types-like-a-pro-a55da6a6a5f7
Статья подробно рассказывает об операторе
&
в TypeScript.Если он работает с примитивными значениями, то понять, каким будет результат просто - этот оператор работает как логическое И:
type T1 = 1 & number; // 1
type T2 = '1' & string; // '1'
type T3 = number & string; // never
Если один из операндов
never
, то результатом будет never
.Если один из операндов
any
, то результатом будет any
.type T4 = any & 1; // any
type T5 = any & boolean; // any
type T6 = any & never; // never
Если же операнды являются объектами, то оператор работает с каждым полем этих объектов.
interface Point {
x: number;
y: number;
}
interface Named {
name: string;
}
type NamedPoint = Point & Named;
// { x: number, y: number, name: string }
Если есть одинаковые поля с конфликтующими типами, будет
never
:interface A {
n: number
}
interface B {
n: string
}
type C = A & B; // { n: never }
В статье есть интересный пример использования пересечения для функций с разной сигнатурой - фактически перегрузка функций с разными наборами параметров.
А в заключение дается пример использования пересечения вместе с MappedTypes, над которым можно немного поломать голову.
#typescript #ссылки #подкапотом
👍3
Использование Typescript с React – руководство для новичков
Статья (рус.): https://habr.com/ru/company/otus/blog/456124/
Небольшое руководство для тех, кто только пытается совместить React и TypeScript в одном приложении. Рассказывает, где именно использовать типы в React.
1) Вместо PropTypes для пропсов компонента.
Тут же мы видим полезный тип
Если кроме указнных пропсов нужно принимать еще стандартные атрибуты HTML-элементов (`style`,
2) Для аргументов в обработчиках событий.
Еще полезный тип
3) Использование дженериков с компонентами
Компоненты React могут принимать обобщенные типы, которые затем могут использоваться для типизации, например, пропсов.
4) Хуки
Типизации требуют в основном два React-хука:
В статье есть пример типизации редуктора, он немного навороченный, но в целом понятный. Главное разобраться, как типизируются экшены с их полезной нагрузкой. Для этого создается отдельный сложный тип
5) typeof и keyof для типизирования компонентов с разными вариантами
Очень удобно, например, для кнопок, которые могут иметь разные стили. При этом набор возможных типов берется из ключей объекта.
#typescript
Статья (рус.): https://habr.com/ru/company/otus/blog/456124/
Небольшое руководство для тех, кто только пытается совместить React и TypeScript в одном приложении. Рассказывает, где именно использовать типы в React.
1) Вместо PropTypes для пропсов компонента.
export interface StandardComponentProps {
title?: string
children: React.ReactNode
}
export function StandardComponent({
children,
title = 'Default Title',
}: StandardComponentProps) {
}
Тут же мы видим полезный тип
ReactNode
.Если кроме указнных пропсов нужно принимать еще стандартные атрибуты HTML-элементов (`style`,
aria-hidden
, `className`), нужно просто расширить существующий встроенный интерфейс React.HTMLAttributes.2) Для аргументов в обработчиках событий.
function onFocus(e: React.FocusEvent) {
console.log('Focused!', e.currentTarget)
}
Еще полезный тип
FocusEvent
. Помимо него есть еще MouseEvent
и, вероятно, ряд других событий.3) Использование дженериков с компонентами
Компоненты React могут принимать обобщенные типы, которые затем могут использоваться для типизации, например, пропсов.
4) Хуки
Типизации требуют в основном два React-хука:
useRef
и useReducer
, остальные работают из коробки. Для этого тоже используются дженерики.В статье есть пример типизации редуктора, он немного навороченный, но в целом понятный. Главное разобраться, как типизируются экшены с их полезной нагрузкой. Для этого создается отдельный сложный тип
Action
, который использует условные типы и пересечения.5) typeof и keyof для типизирования компонентов с разными вариантами
Очень удобно, например, для кнопок, которые могут иметь разные стили. При этом набор возможных типов берется из ключей объекта.
const styles = {
primary: {
color: 'blue',
},
danger: {
color: 'red',
},
};
type StylesType = typeof styles;
export type ButtonType = keyof StylesType;
interface ButtonProps {
type: ButtonType
};
export function Button({ type = 'primary' }: ButtonProps) {
}
#typescript
Хабр
Использование Typescript с React – руководство для новичков
Друзья, в преддверии выходных хотим поделиться с вами еще одной интересной публикацией, которую хотим приурочить к запуску новой группы по курсу «Разработчик Jav...
👍3👎1
Typescript. Утилиты. Часть 4 (Uppercase, Lowercase, Capitalize, Uncapitalize)
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Третья часть (Parameters, ReturnType): https://yangx.top/react_junior/430
В этот раз 4 очень простые утилиты, которые имеют дело с регистром символов:
- Uppercase
- Lowercase
- Capitalize
- Uncapitalize
#typescript
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Третья часть (Parameters, ReturnType): https://yangx.top/react_junior/430
В этот раз 4 очень простые утилиты, которые имеют дело с регистром символов:
- Uppercase
- Lowercase
- Capitalize
- Uncapitalize
#typescript
🔥2
TypeScript. Ключевое слово infer
Весь вечер пытаюсь разобраться с ключевым словом infer в TypeScript 🙂 Не сказать, что концепция самая очевидная, но вроде и не чрезмерно сложная, если я, конечно, все правильно понимаю.
Итак, infer может "выводить" один тип на основании другого. Использовать это ключевое слово можно только в условных конструкциях вместе с extend. Выведенный тип затем можно использовать, например, вернуть из условной конструкции.
Подробнее об условных типах: https://yangx.top/react_junior/431
Самый понятный для меня (но вероятно не самый популярный) пример использования infer - на приложенном скрине (взято со StackOverflow).
Утилита UnpackArrayType получает обобщенный тип T.
Затем ставится условие:
T extends (infer R)[]
Эта конструкция буквально означает, "можно ли представить T в виде массива элементов какого-нибудь типа R". При этом тип R буквально "выводится" из типа T с помощью infer. Если T равно number[], то R будет равно number.
Если условие получилось выполнить, возвращается свежевыведенный тип R.
Неплохой разбор infer есть в статье Understanding infer in TypeScript (англ.)
Там автор начинает с более простых концепций: типа never, оператора extends, объединений, а затем переходит к работе с функциями и собственно ключевому слову infer.
К слову, именно infer лежит в основе работы утилиты ReturnType.
В конце статьи приводяется некоторые популярные кейсы использования infer, например, выведение возвращаемого типа из промиса.
#ссылки #typescript #подкапотом #infer
Весь вечер пытаюсь разобраться с ключевым словом infer в TypeScript 🙂 Не сказать, что концепция самая очевидная, но вроде и не чрезмерно сложная, если я, конечно, все правильно понимаю.
Итак, infer может "выводить" один тип на основании другого. Использовать это ключевое слово можно только в условных конструкциях вместе с extend. Выведенный тип затем можно использовать, например, вернуть из условной конструкции.
Подробнее об условных типах: https://yangx.top/react_junior/431
Самый понятный для меня (но вероятно не самый популярный) пример использования infer - на приложенном скрине (взято со StackOverflow).
Утилита UnpackArrayType получает обобщенный тип T.
Затем ставится условие:
T extends (infer R)[]
Эта конструкция буквально означает, "можно ли представить T в виде массива элементов какого-нибудь типа R". При этом тип R буквально "выводится" из типа T с помощью infer. Если T равно number[], то R будет равно number.
Если условие получилось выполнить, возвращается свежевыведенный тип R.
Неплохой разбор infer есть в статье Understanding infer in TypeScript (англ.)
Там автор начинает с более простых концепций: типа never, оператора extends, объединений, а затем переходит к работе с функциями и собственно ключевому слову infer.
К слову, именно infer лежит в основе работы утилиты ReturnType.
В конце статьи приводяется некоторые популярные кейсы использования infer, например, выведение возвращаемого типа из промиса.
#ссылки #typescript #подкапотом #infer
👍5
Статья (англ.): https://levelup.gitconnected.com/using-typescript-infer-like-a-pro-f30ab8ab41c7
Еще немного про infer (начало здесь)
В статье приводится очень хорошее пошаговое объяснение того, как работает это ключевое слово.
Infer буквально распаковывает тип и позволяет вывести из него другой тип.
Рассматривается тот же пример с распаковкой массива и получением типа элемента (только подробнее и с анимацией).
Кроме того есть примеры с распаковкой аргументов и возвращаемого значения функций (так работает под капотом утилита ReturnType) и распаковкой ключей объекта.
Важно помнить, что infer может использоваться только в условных типах (`extends`) и после "захвата" доступен только в true-части выражения.
Во второй части статьи рассматриваются тонкости работы ключевого слова infer, например, при множественных типах (иногда в результате получается объединение типов, а иногда пересечение), а также сочетание нескольких условий.
В конце задачка, которая сломала мой мозг 🤯
#typescript #infer
Еще немного про infer (начало здесь)
В статье приводится очень хорошее пошаговое объяснение того, как работает это ключевое слово.
Infer буквально распаковывает тип и позволяет вывести из него другой тип.
Рассматривается тот же пример с распаковкой массива и получением типа элемента (только подробнее и с анимацией).
Кроме того есть примеры с распаковкой аргументов и возвращаемого значения функций (так работает под капотом утилита ReturnType) и распаковкой ключей объекта.
Важно помнить, что infer может использоваться только в условных типах (`extends`) и после "захвата" доступен только в true-части выражения.
Во второй части статьи рассматриваются тонкости работы ключевого слова infer, например, при множественных типах (иногда в результате получается объединение типов, а иногда пересечение), а также сочетание нескольких условий.
В конце задачка, которая сломала мой мозг 🤯
#typescript #infer
👍4
По TypeScript получилось довольно много материала (и еще будет 😄), поэтому добавлены новые теги для сложных тем: #infer, #дженерики и #tsдекораторы
Все теги тут: https://yangx.top/react_junior/84
Все теги тут: https://yangx.top/react_junior/84
Telegram
React Junior
Список тегов для более удобного поиска постов
👉 Основные понятия
#компоненты
#jsx
#жизненныйциклкомпонента
#виртуальныйdom
#состояние
#обработкасобытий
#потокданных
#ключи
#формы
#рефы
#hoc
#рендерпропсы
#контекст
#порталы
#хуки
👉 Управление состоянием…
👉 Основные понятия
#компоненты
#jsx
#жизненныйциклкомпонента
#виртуальныйdom
#состояние
#обработкасобытий
#потокданных
#ключи
#формы
#рефы
#hoc
#рендерпропсы
#контекст
#порталы
#хуки
👉 Управление состоянием…
🔥3
TypeScript. Шаблонные литералы
Статья (англ.): https://javascript.plainenglish.io/how-to-use-typescript-template-literal-types-like-a-pro-2e02a7db0bac
В типах тоже можно использовать шаблонные строки, а вставлять в них можно другие типы (в том числе, объединения типов).
В статье подробно и с картинками рассказано, во что именно компилируются типы с использованием шаблонных строк.
В шаблонных строках можно также использовать утилиты, работающие со строками (Uppercase, Lowercase, Capitalize, Uncapitalize).
Также их можно использовать в условных типах в сочетании с ключевым словом infer для создания очень мощных условий.
В статье разобрано использование шаблонных строк для Key Remapping (переименования ключей в сопоставимых типах).
А в самом конце есть прекрасный пример рекурсивной работы с типами.
#typescript
Статья (англ.): https://javascript.plainenglish.io/how-to-use-typescript-template-literal-types-like-a-pro-2e02a7db0bac
В типах тоже можно использовать шаблонные строки, а вставлять в них можно другие типы (в том числе, объединения типов).
type Alignment = 'start' | 'end';
type Side = 'top' | 'right' | 'bottom' | 'left';
type AlignedPlacement = `${Side}-${Alignment}`;
В статье подробно и с картинками рассказано, во что именно компилируются типы с использованием шаблонных строк.
В шаблонных строках можно также использовать утилиты, работающие со строками (Uppercase, Lowercase, Capitalize, Uncapitalize).
Также их можно использовать в условных типах в сочетании с ключевым словом infer для создания очень мощных условий.
В статье разобрано использование шаблонных строк для Key Remapping (переименования ключей в сопоставимых типах).
А в самом конце есть прекрасный пример рекурсивной работы с типами.
#typescript
🔥3👍2
Typescript. Утилиты. Часть 5 (Pick, Omit)
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Третья часть (Parameters, ReturnType): https://yangx.top/react_junior/430
Четвертая часть (Uppercase, Lowercase, Capitalize, Uncapitalize): https://yangx.top/react_junior/435
Утилита
Эта утилита похожа на Mapped Types, только Mapped Types берут полный набор ключей из исходного типа, а для
#typescript
Первая часть (Readonly, Required, Partial): https://yangx.top/react_junior/413
Вторая часть (Exclude, Extract, NonNullable): https://yangx.top/react_junior/429
Третья часть (Parameters, ReturnType): https://yangx.top/react_junior/430
Четвертая часть (Uppercase, Lowercase, Capitalize, Uncapitalize): https://yangx.top/react_junior/435
Утилита
Pick
получает два параметра: исходный тип и набор ключей. Результат работы - новый тип на основе исходного, в который входят только указанные ключи.Эта утилита похожа на Mapped Types, только Mapped Types берут полный набор ключей из исходного типа, а для
Pick
набор ключей заранее указан.Omit
, соответственно, работает наоборот, берет все ключи, кроме указанных. Под капотом использует Pick
и Exclude
, чтобы получить набор нужных для типа ключей.#typescript
Telegram
React Junior
TypeScript. Утилиты (Readonly, Required, Partial)
TypeScript не просто дает возможность указыать типы для переменных и параметров и тем самым отслеживать ошибки. Он еще предлагает большой инструментарий для манипуляций с типами, превращения одних типов в…
TypeScript не просто дает возможность указыать типы для переменных и параметров и тем самым отслеживать ошибки. Он еще предлагает большой инструментарий для манипуляций с типами, превращения одних типов в…
👍1🔥1
TypeScript. 15 самых популярных утилит
Статья (англ.): https://javascript.plainenglish.io/15-utility-types-that-every-typescript-developer-should-know-6cf121d4047c
С большинством из перечисленных в статье утилит мы уже знакомы.
Partial, Required, Readonly
Функциональность этих утилит разбирали здесь: https://yangx.top/react_junior/413
А подкапотную реализацию здесь (статья о Mapped Types): https://yangx.top/react_junior/428
Для перебора ключей используется конструкция
Exclude, Extract, NonNullable
Функциональность тут: https://yangx.top/react_junior/429
Реализованы на условных типах: https://yangx.top/react_junior/431
Члены одного набора типов сопоставляются с членами второго набора с помощью конструкции
Pick, Omit
Функциональность и реализация тут: https://yangx.top/react_junior/442
Напоминают Mapped Types.
Parameters, ReturnType
Функциональность тут: https://yangx.top/react_junior/430
В реализации используется ключевое слово infer https://yangx.top/react_junior/439, чтобы вытащить нужные типы из полученного типа функции.
Uppercase, Lowercase, Capitalize, Uncapitalize
Функциональность здесь: https://yangx.top/react_junior/435
Record
С этой утилитой мы еще не встречались.
Она принимает два обобщенных типа: набор ключей Keys и тип значений Type. Из них формируется новый тип, в котором есть все ключи из Keys и каждому из них соответствует значение типа Type.
Условно это выглядит так:
#typescript
Статья (англ.): https://javascript.plainenglish.io/15-utility-types-that-every-typescript-developer-should-know-6cf121d4047c
С большинством из перечисленных в статье утилит мы уже знакомы.
Partial, Required, Readonly
Функциональность этих утилит разбирали здесь: https://yangx.top/react_junior/413
А подкапотную реализацию здесь (статья о Mapped Types): https://yangx.top/react_junior/428
Для перебора ключей используется конструкция
P in keyof T
.Exclude, Extract, NonNullable
Функциональность тут: https://yangx.top/react_junior/429
Реализованы на условных типах: https://yangx.top/react_junior/431
Члены одного набора типов сопоставляются с членами второго набора с помощью конструкции
T extends U ? X : Y
Pick, Omit
Функциональность и реализация тут: https://yangx.top/react_junior/442
Напоминают Mapped Types.
Parameters, ReturnType
Функциональность тут: https://yangx.top/react_junior/430
В реализации используется ключевое слово infer https://yangx.top/react_junior/439, чтобы вытащить нужные типы из полученного типа функции.
Uppercase, Lowercase, Capitalize, Uncapitalize
Функциональность здесь: https://yangx.top/react_junior/435
Record
С этой утилитой мы еще не встречались.
Она принимает два обобщенных типа: набор ключей Keys и тип значений Type. Из них формируется новый тип, в котором есть все ключи из Keys и каждому из них соответствует значение типа Type.
Условно это выглядит так:
type Keys = 101 | 102 | 103; // набор ключей
type User = { name: string; age: number }; // тип значений
// результат
type Record = {
101: User,
102: User,
103: User
}
#typescript
Medium
TypeScript Visualized: 15 Most Used Utility Types
15 Utility Types that Every TypeScript Developer Should Know
👍3🔥2
10 вещей, которые нужно знать о классах в TypeScript
Статья (англ.): https://levelup.gitconnected.com/10-things-you-need-to-know-about-typescript-classes-f58c57869266
Достаточно полный справочник по классам в TypeScript.
Первые пункты простые:
1. Статические поля и поля класса
2. Геттеры и сеттеры
3. Наследование классов (и реализация интерфейсов)
4. Абстрактные классы
5. Модификаторы доступа (и их сочетание с ECMAScript Private Fields)
6. Class Expressions
7. Использование дженериков в классах (https://yangx.top/react_junior/405)
Дальше посложнее: про конструкторы (и абстрактные конструкторы) и про использование в качестве типа самого класса и
Но если что тип для функции-конструктора на скрине.
#typescript
Статья (англ.): https://levelup.gitconnected.com/10-things-you-need-to-know-about-typescript-classes-f58c57869266
Достаточно полный справочник по классам в TypeScript.
Первые пункты простые:
1. Статические поля и поля класса
2. Геттеры и сеттеры
3. Наследование классов (и реализация интерфейсов)
4. Абстрактные классы
5. Модификаторы доступа (и их сочетание с ECMAScript Private Fields)
6. Class Expressions
7. Использование дженериков в классах (https://yangx.top/react_junior/405)
Дальше посложнее: про конструкторы (и абстрактные конструкторы) и про использование в качестве типа самого класса и
typeof Class
. Это все пока не очень понятно, как использовать.Но если что тип для функции-конструктора на скрине.
#typescript
👍3🔥2
Next.js + TypeScript
Для описания страниц в Next-приложении нам потребуется тип
#nextjs #серверныйрендеринг #typescript
Для описания страниц в Next-приложении нам потребуется тип
NextPage
(импортируется из пакета next). Это дженерик, который принимает тип пропсов компонента.#nextjs #серверныйрендеринг #typescript
👍2🔥1
Не могу удержаться и не поделиться) Вчера впервые потребовалось использовать
Ни на что не претендую, просто небольшой пример практического применения не самой простой концепции.
#примерыкода #typescript #infer
infer
в боевых условиях: https://telegra.ph/Infer-v-TypeScript-primer-ispolzovaniya-01-21Ни на что не претендую, просто небольшой пример практического применения не самой простой концепции.
#примерыкода #typescript #infer
Telegraph
Infer в TypeScript: пример использования
Мой первый самостоятельный кейс использования ключевого слова infer. Не могу не поделиться :) Есть условная функция fetchAndFormat, которая получает данные из api и форматирует их. У нее два аргумента: fetcherFn и formatterFn. Причем второй - необязательный…
👍8
TypeScript в Next.js
Соберем в одном месте типы, которые использует Next:
Данные для серверного рендеринга - GetStaticProps, GetStaticPaths, GetServerSideProps
API-роуты - NextApiRequest, NextApiResponse
Тип
Компонент App - AppProps
#nextjs #документация #typescript
Соберем в одном месте типы, которые использует Next:
Данные для серверного рендеринга - GetStaticProps, GetStaticPaths, GetServerSideProps
import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next';
export const getStaticProps: GetStaticProps = async function (context) {
// ...
}
export const getStaticPaths: GetStaticPaths = async function () {
// ...
}
export const getServerSideProps: GetServerSideProps = async function (context) {
// ...
}
API-роуты - NextApiRequest, NextApiResponse
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({ name: 'John Doe' })
}
Тип
NextApiResponse
может также принимать обобщенный тип данных ответа.Компонент App - AppProps
import type { AppProps } from 'next/app'
export default function MyApp({ Component, pageProps }: AppProps) {
// ...
}
#nextjs #документация #typescript
👍3🔥1
React: самые используемые типы
Статья (англ.): https://jser.dev/2023-05-31-react-types-in-typescript/
Автор статьи сделал подборку типов, используемых в React, чтобы нам не пришлось.
1. ReactElement
Главный "строительный" метод React - React.createElement(). Он принимает конфиг элемента, который нужно создать - его и описывает интерфейс ReactElement.
ReactElement или JSX.Element (то же самое, просто алиас) - это то, что должно быть возвращено из JSXElementConstructor (из функционального или классового компонента).
2. ReactNode
Это "надтип" для ReactElement, как и в DOM - есть ноды (включают комментарии и текстовые узлы), а есть их подмножество - элементы.
В тип ReactNode входят ReactElement, строки, числа, булевы значения, фрагменты, порталы и даже null и undefined
3. FunctionComponent
Интерфейс, описывающий функциональный компонент
4. RefObject и MutableRefObject
Типы, описывающие рефы, созданные хуком
У
5. ComponentProps
Обобщенный тип, позволяющий "извлечь" из типа компонента его пропсы. Под капотом использует infer.
6. Dispatch и SetStateAction
Эти типы описывают самый популярный хук
Тип
7. События
С типизацией событий в React всегда сложно. Есть два подхода:
- типизировать само событие (SyntheticEvent), которое приходит в обработчик в виде аргумента, например, MouseEvent
- или типизировать сам обработчик - MouseEventHandler
Оба типа - дженерики, которым можно передать тип элемента, на котором происходит событие.
#typescript #ссылки
Статья (англ.): https://jser.dev/2023-05-31-react-types-in-typescript/
Автор статьи сделал подборку типов, используемых в React, чтобы нам не пришлось.
1. ReactElement
Главный "строительный" метод React - React.createElement(). Он принимает конфиг элемента, который нужно создать - его и описывает интерфейс ReactElement.
interface ReactElement {
type: T,
props: P,
key: Key | null,
}
ReactElement или JSX.Element (то же самое, просто алиас) - это то, что должно быть возвращено из JSXElementConstructor (из функционального или классового компонента).
2. ReactNode
Это "надтип" для ReactElement, как и в DOM - есть ноды (включают комментарии и текстовые узлы), а есть их подмножество - элементы.
В тип ReactNode входят ReactElement, строки, числа, булевы значения, фрагменты, порталы и даже null и undefined
3. FunctionComponent
Интерфейс, описывающий функциональный компонент
4. RefObject и MutableRefObject
Типы, описывающие рефы, созданные хуком
useRef
. У
useRef
есть несколько перезагрузок и одна из них приводит к тому, что поле ref.current
становится readonly
и его нельзя изменить 😳5. ComponentProps
Обобщенный тип, позволяющий "извлечь" из типа компонента его пропсы. Под капотом использует infer.
6. Dispatch и SetStateAction
Эти типы описывают самый популярный хук
useState
.Тип
Dispatch
- это просто функция, которая принимает аргумент заявленного типа и ничего не возвращает.SetStateAction
- это либо новое состояние, либо функция, которая принимает старое состояние и возвращает новое.7. События
С типизацией событий в React всегда сложно. Есть два подхода:
- типизировать само событие (SyntheticEvent), которое приходит в обработчик в виде аргумента, например, MouseEvent
- или типизировать сам обработчик - MouseEventHandler
Оба типа - дженерики, которым можно передать тип элемента, на котором происходит событие.
#typescript #ссылки
jser.dev
React types in TypeScript
Demystify the common React types in TypeScript
👍3
Вариантность и совместимость типов в TypeScript
Попробуем разобраться, что такое ковариантность и контравариантность и на что они влияют в TypeScript.
Подтип и супертип
Сначала определим основные понятия - подтип и супертип.
Подтип расширяет супертип.
⁃ Dog - это подтип, Animal - это супертип.
⁃ String - это подтип, Object - это супертип.
⁃ number - это подтип, any - это супертип.
Мы пишем, что подтип меньше супертипа (SubType <: SuperType), однако по факту, в подтипе больше информации, чем в супертипе, потому что подтип буквально расширяет супертип. Подтип «избыточен» по сравнению с супертипом.
Любое значение с типом SubType всегда является одновременно значением типа SuperType, так как имеет все необходимые для SuperType поля.
Структурная типизация
Важно понимать, что в TypeScript подтип и супертип необязательно связаны отношениями наследования (class Dog extends Animal). TypeScript реализует структурную типизацию и ориентируется только на структуру типов.
Типы Animal и Dog никак не связаны между собой, но Dog все равно является подтипом для Animal.
Ковариантность как основная стратегия
Когда мы пытаемся присвоить значение какой-то переменной в TypeScript, компилятор смотрит, а соответствует ли тип этого значения объявленному типу этой переменной, совместимы ли они, можно ли положить это значение в эту переменную.
Есть конкретные правила для определения совместимости. В большинстве случаев верно утверждение:
⁃ Вы можете безопасно использовать подтип там, где ожидается супертип.
Довольно просто понять, почему так сделано - значение с типом SubType также является значением типа SuperType, поэтому тут нет противоречий. Если программа готова справиться с Animal (супертип), значит, она справится и с Dog (подтип), ведь он предоставляет те же самые данные.
Такая стратегия называется Ковариантностью. Она разрешает «избыточность» типа и запрещает «недостаточность».
Контравариантность для параметров функций
Стратегия ковариантности действует везде, кроме одного места - определения совместимости функций.
Казалось бы, Foo2 является подтипом для Foo1 (Foo2 <: Foo1), а значит функцию типа Foo2 должно быть можно положить в переменную с типом Foo1:
Но мы получаем ошибку. При этом наоборот все работает:
Здесь тоже несложно понять, почему так. Программа ожидает функцию с одним аргументом и передает ей только один аргумент. Если на этом месте окажется функция, ожидающая больше аргументов, она их просто не получит.
В обратную сторону тоже все хорошо. Даже если программа ожидает функцию с двумя аргументами и передает два аргумента, а в сигнатуре функции указан лишь один, ничего не сломается. Функция получит свой аргумент, а второй - ненужный - просто проигнорирует.
Такая стратегия называется «контравариантность». Она разрешает «недостаточность» типа и запрещает «избыточность».
#typescript
Попробуем разобраться, что такое ковариантность и контравариантность и на что они влияют в TypeScript.
Подтип и супертип
Сначала определим основные понятия - подтип и супертип.
Подтип расширяет супертип.
⁃ Dog - это подтип, Animal - это супертип.
⁃ String - это подтип, Object - это супертип.
⁃ number - это подтип, any - это супертип.
Мы пишем, что подтип меньше супертипа (SubType <: SuperType), однако по факту, в подтипе больше информации, чем в супертипе, потому что подтип буквально расширяет супертип. Подтип «избыточен» по сравнению с супертипом.
Любое значение с типом SubType всегда является одновременно значением типа SuperType, так как имеет все необходимые для SuperType поля.
Структурная типизация
Важно понимать, что в TypeScript подтип и супертип необязательно связаны отношениями наследования (class Dog extends Animal). TypeScript реализует структурную типизацию и ориентируется только на структуру типов.
type Animal = {
name: string
}
type Dog = {
name: string
breed: string
}
Типы Animal и Dog никак не связаны между собой, но Dog все равно является подтипом для Animal.
Ковариантность как основная стратегия
Когда мы пытаемся присвоить значение какой-то переменной в TypeScript, компилятор смотрит, а соответствует ли тип этого значения объявленному типу этой переменной, совместимы ли они, можно ли положить это значение в эту переменную.
Есть конкретные правила для определения совместимости. В большинстве случаев верно утверждение:
⁃ Вы можете безопасно использовать подтип там, где ожидается супертип.
let a: any = 42 // number <: any
let b: Animal = new Dog() // Dog <: Animal
Довольно просто понять, почему так сделано - значение с типом SubType также является значением типа SuperType, поэтому тут нет противоречий. Если программа готова справиться с Animal (супертип), значит, она справится и с Dog (подтип), ведь он предоставляет те же самые данные.
Такая стратегия называется Ковариантностью. Она разрешает «избыточность» типа и запрещает «недостаточность».
Контравариантность для параметров функций
Стратегия ковариантности действует везде, кроме одного места - определения совместимости функций.
type Foo1 = (param: number) => void
type Foo2 = (param1: number, param2: string) => void
Казалось бы, Foo2 является подтипом для Foo1 (Foo2 <: Foo1), а значит функцию типа Foo2 должно быть можно положить в переменную с типом Foo1:
let foo1: F1 = (param1: number, param2: string) => {} // Error
Но мы получаем ошибку. При этом наоборот все работает:
let foo2: F2 = (param1: number) => {} // Ok
Здесь тоже несложно понять, почему так. Программа ожидает функцию с одним аргументом и передает ей только один аргумент. Если на этом месте окажется функция, ожидающая больше аргументов, она их просто не получит.
В обратную сторону тоже все хорошо. Даже если программа ожидает функцию с двумя аргументами и передает два аргумента, а в сигнатуре функции указан лишь один, ничего не сломается. Функция получит свой аргумент, а второй - ненужный - просто проигнорирует.
Такая стратегия называется «контравариантность». Она разрешает «недостаточность» типа и запрещает «избыточность».
#typescript
👍3🌭1
Как устроена система типов в TypeScript
Статья (рус.): https://ru.hexlet.io/blog/posts/sistema-tipov-v-typescript
В статье разбирается стратегия ковариантности типов на основе принципе подстановки Барбары Лисков: поведение подтипа не должно противоречить поведению супертипа.
Объясняется, что подтип более строгий, чем супертип, так как ему соответствует меньше значений (собственно поэтому SubType < SuperType).
Немного говорится об иерархии типов в TypeScript, особенностях типов any, unknown, never и void.
Приводится простой способ проверить соответствие:
Статья также рассказывает о двух видах приведения типов:
⁃ восходящем (безопасное приведение подтипа к супертипу, происходит неявно)
⁃ нисходящее (приведение супертипа к подтипу, должно быть явным)
Обычно восходящее приведение происходит неявно, автоматически, но есть две ситуации, в которых оно запрещено - при работе с литеральными объектами (которые создаются на месте использования).
В общем, хорошая статья, подводящая под довольно сложную тему хороший теоретический базис.
#typescript
Статья (рус.): https://ru.hexlet.io/blog/posts/sistema-tipov-v-typescript
В статье разбирается стратегия ковариантности типов на основе принципе подстановки Барбары Лисков: поведение подтипа не должно противоречить поведению супертипа.
Объясняется, что подтип более строгий, чем супертип, так как ему соответствует меньше значений (собственно поэтому SubType < SuperType).
Немного говорится об иерархии типов в TypeScript, особенностях типов any, unknown, never и void.
Приводится простой способ проверить соответствие:
type A = string extends unknown ? true : false // true
type B = unknown extends string ? true : false // false
Статья также рассказывает о двух видах приведения типов:
⁃ восходящем (безопасное приведение подтипа к супертипу, происходит неявно)
⁃ нисходящее (приведение супертипа к подтипу, должно быть явным)
Обычно восходящее приведение происходит неявно, автоматически, но есть две ситуации, в которых оно запрещено - при работе с литеральными объектами (которые создаются на месте использования).
В общем, хорошая статья, подводящая под довольно сложную тему хороший теоретический базис.
#typescript
Хекслет
Как устроена система типов в TypeScript
Перевели большую статью бывшего разработчика Amazon Web Services Хэ Чжэнхао и узнали, что такое иерархия типов в TypeScript и как они соотносятся между собой.
👍3