Skip to content

Instantly share code, notes, and snippets.

@RubaXa
RubaXa / describe.title.tsx
Last active August 26, 2019 15:26
Poor slots. Describe. Title.
type LoginFormProps = {
title?: React.ReactNode; // ⬅ Хоп 1️⃣
email?: string;
password?: string;
}
function LoginForm(props: LoginFormProps) {
return (
<Form>
<div className="header">
@RubaXa
RubaXa / describe.tsx
Last active August 26, 2019 15:19
Poor slots. Describe.
type LoginFormProps = {
email?: string;
password?: string;
}
function LoginForm(props: LoginFormProps) {
return (
<Form>
<div className="header">
<h2>Вход</h2>
@RubaXa
RubaXa / types.ts
Last active July 17, 2019 09:30
TrueKit. AllDeps. Types.
// 1️⃣Первым делом нам понадобиться тип извлекающий `DescriptorWithMetaMap`
type GetMetaDeps<T> = T extends {deps?: infer D} ? GetMeta<D> : never;
// Реузльтат для GetMetaDeps<FormProps>, как я уже писал выше, будет:
// {
// Input: DescriptorWithMeta<"myapp/Input", InputProps>;
// Btn: DescriptorWithMeta<"myapp/Btn", BtnProps>;
// }
// 2️⃣Теперь нам надо преобразовать этот объект в `depId => LikeComponent<{...}>`
@RubaXa
RubaXa / components.tsx
Last active July 16, 2019 16:14
TrueKit. Form. Components.
// 1️⃣ Иконка (без зависимостей)
type IconProps = {
name: string;
theme?: Theme<{...}>;
}
// Декскриптор иконки
const $Icon = createComponentDescriptor('myapp/Icon', {} as IconProps, {});
// Компонент на основе дескриптора иконки
@RubaXa
RubaXa / DepsInline.ts
Last active June 16, 2019 08:24
Deps Inline Type
// Вот теперь можно описать нужный нам тип
type DepsInline<T extends DescriptorWithMetaMap> = CastIntersect< // 3️⃣
{ // ⬇️Итерируемся по ключам и проверяем, является ли свойство
// опциональным или нет, если да, то создаём объект с необязальным ключем
[K in keyof T]: IsOptional<T[K]> extends true // 1️⃣
? { [X in K]?: LikeComponent<NonNullable<T[K]>['meta']> }
: { [X in K]: LikeComponent<NonNullable<T[K]>['meta']> }
}[keyof T], // 2️⃣
object
>
@RubaXa
RubaXa / optional.type.ts
Created June 16, 2019 08:15
Optional types
// Вспомогательный тип, который добавляет `undefined`
type Optional<T> = T | undefined;
// Тип, который проверяет на `optional`, путем преобразования входящего
// дженерика в `intersect` и проверкой на вхождение в него `undefined`
type IsOptional<T> = ToIntersect<T> extends undefined ? true : false;
@RubaXa
RubaXa / union-to-intersect.ts
Created June 16, 2019 08:09
Union To Intersect
export type UnionToIntersect<U> =
(U extends any
? (inp: U) => void
: never
) extends ((out: infer I) => void)
? I
: never
;
@RubaXa
RubaXa / cast-meta.ts
Last active July 16, 2019 15:23
Cast & Meta types
// Думаю тут нет нужды в объяснениях:
export type Cast<X, Y> = X extends Y ? X : Y;
// А вот для `Meta`, нам понадобиться символ, ибо его «можно» ⤵️ (см. ниже)
export const __meta__ = Symbol('__meta__');
// «Можно» использовать для описания свойства объекта:
export type Meta<T> = {
[__meta__]?: T; // так же можно использовать и литералы, но символ пизже!
// т.е. его нельзя будет увидеть через autocomplete 👀
@RubaXa
RubaXa / deps.types.ts
Last active July 16, 2019 15:20
TrueKit. Deps types.
// Создаём дескриптор компонента с описанием его зависимостей
const $Form = createComponentDescriptor('@truekit/Form', {} as FormProps, {
// Как я уже говорил, описание зависимосей являются другие дескрипторы
Input: $Input,
Button: $Button,
Checkbox: $Checkbox.optional(), // необязательная зависимость
});
type FormProps = {
// бли-бла-бла
@RubaXa
RubaXa / descriptor.types.ts
Last active June 16, 2019 06:52
TrueKit. Descriptor Types.
export interface Descriptor<ID extends string> {
readonly id: ID;
readonly isOptional: boolean;
optional(): this | undefined; // ⬅️Вот это очень важный момент,
// undefined нужен как часть типа❗️
// Дальше, этот undefined нужен будет,
// чтобы определить, является ли зависисимость
// обязательной, или нет
}