Pull to refresh

Comments 23

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

С одной стороны тайпскрипт является хорошей попыткой типизировать JS, закрывая один пласт проблем, но с другой стороны вносит другой пласт проблем поверх и так проблемного JS. Смотря на подобные вещи и на ошибки в багтрекере, понимаешь что это хождение по тонкому льду. Может это только моё субъективное мнение, но ощущается это именно так.

Выглядит как магия.

У нас по этому поводу в компании ходит шутка: 'В коде не должно быть никакой магии, а волшебство — пожалуйста'

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

Я не автор, но попробую ответить.


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


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


  1. Использовать под интерфейсы. Меняя структуру данных.
  2. Делать юнионы, при разумных количествах комбинаций.
  3. Забить.
Находка: Восклицательный знак в роли Non-null assertion operator

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

Этот оператор не имеет никакого отношения к приведению к boolean. Этот оператор убирает null из типа.

невнимательно прочитал, оказывается речь шла не про assertion, а про подавление warning optType.maybe!.data
+ к статье
На тайпскрипте можно написать ограниченный итератор (на 40 шагов), что позволяет делать некоторые крутые штуки
github.com/pirix-gh/ts-toolbelt/blob/master/src/Tuple/Drop.ts
как пример
Кажется это можно использовать для такой задачи
[{key: 'a', value: 'b'}, {key: 'b', value: 'c'}] в {a: 'b', b: 'c'}

Это ирония или я чего-то не понимаю? Чем плох reduce?


[{key: 'a', value: 'b'}, {key: 'b', value: 'c'}].reduce((acc, elem) => ({ ...acc, [elem.key]: elem.value }), {})
Я про конвертацию типов а не реальных значений
type arr = [{key: 'a', value: 'b'}, {key: 'b', value: 'c'}];
type obj = {
    [K in arr[number]['key']]: Extract<arr[number], {key: K}>['value']
};
const obj: obj = {a: 'b', b: 'c'} // ошибки нет
const wrong1: obj = {}; // не хватает параметров
const wrong2: obj = {a: 'b', b: 'c', c: 'd'} // параметр c лишний
const wrong3: obj = {a: 'b', b: 1} // параметр b не того типа

Что я делаю не так?


upd: хабр, запили подсветку TS ><

Блин, прикольно, даже не думал об таком подходе
За ссылку спасибо, в какой-то мере там кладезь знаний по типа ts

С другой стороны, там очень сильно перемудрили. Например, вместо типа true ввели тип True=1. Аналогичные обёртки запилили над всеми типами. Или вместо двух обобщённых типов понавтыкали один с флагом. Или вкорячили арифметику для чисел от -40 до 40. Короче, как источник идей как типизировать что-то хитрое типа Compose использовать можно, но тянуть в проект такое я бы поостерёгся.

Кажется это можно использовать для такой задачи

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


type List = [number, string, boolean, undefined];
type DroppedList1 = Drop<MyList, 1>; // [string, boolean, undefined]
type DroppedList2 = Drop<MyList, 2>; // [boolean, undefined]

https://www.freecodecamp.org/news/typescript-curry-ramda-types-f747e99744ab/


В этой статье есть много про паттерны для работы с кортежами.

Не, я в целом имел ввиду подход к итерации на уровне типов
Магия TS мне очень нравится. Однако разбираться и разбираться в ней.
Например, попробовал сделать маппер, с полной поддержкой TS
interface MyMapper<F, T, TK extends keyof T> {
    field: keyof F;
    map: IMapScheme<F, T[TK]>; 
}

type IMapScheme<F, T> = {
    [TK in keyof T]: keyof F | MyMapper<F, T, TK>;
};

interface From {
    _id: string;
    name: string;
    data: {
        foo: string;
        bar: string;
    };
}

interface To {
    id: string;
    name: string;
    meta: {
        fooData: string;
    };
}

const Try1Scheme: IMapScheme<From, To> = {
    id  : '_id',
    name: 'name',
    meta: {
        field: 'data',
        map  : {
            fooData: 'foo',
        },
    },
};


И очень просится написать что-то на подобии
interface MyMapper<F, T, TK extends keyof T> {
    field: keyof F;
    map: IMapScheme<F[this.field], T[TK]>; 
}


Такая магия возможна?

Не очень понял зачем вам эти типы. Просто напишите функцию-маппер и возльмите от неё typeof.

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

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

Задачка интересная. Сходу мне решить ее не удалось. Подумаю на досуге.
Only those users with full accounts are able to leave comments. Log in, please.