Forwarded from TypeScript Challenge
Type Challenges #12. Chainable Options
Ссылка на задачу
Ссылка на песочницу с тестами
Условие
У нас есть некий объект/класс с двумя методами:
Задача: типизировать класс
Важный момент: нельзя два раза передать в
Решение
Тут нам нужно решить две задачи:
- сохранять переданные ключи и значения, чтобы набрать нужный тип и вернуть его в
- запретить передавать один ключ дважды - для этого будем проверять, если ли у нас уже такой ключ и возвращать
#medium
Ссылка на задачу
Ссылка на песочницу с тестами
Условие
У нас есть некий объект/класс с двумя методами:
option(key, value)
и get()
. В первый можно передать имя поля (строка) и любое значение для него. Таким образом мы "набираем" себе объект с нужными полями. Причем вызовы метода option
можно объединять в цепочку (чейнить). Метод get
возвращает этот "собранный" объект.
declare const config: Chainable
const result = config
.option('foo', 123)
.option('name', 'type-challenges')
.option('bar', { value: 'Hello World' })
.get()
interface Result {
foo: number
name: string
bar: { value: string }
}
Задача: типизировать класс
Chainable
.Важный момент: нельзя два раза передать в
option
одно и то же свойство.Решение
Тут нам нужно решить две задачи:
- сохранять переданные ключи и значения, чтобы набрать нужный тип и вернуть его в
get
- для этого сделаем Chainable
дженериком и будем просто дописывать новые данные - запретить передавать один ключ дважды - для этого будем проверять, если ли у нас уже такой ключ и возвращать
never
если нет
type Chainable<T = {}> = {
option: <K extends string, V>(
key: K extends keyof T ? never : K,
value: V
) => Chainable<Omit<T, K> & Record<K, V>>;
get: () => T;
}
#medium
GitHub
type-challenges/questions/00012-medium-chainable-options/README.md at main · type-challenges/type-challenges
Collection of TypeScript type challenges with online judge - type-challenges/type-challenges
👍2
Forwarded from TypeScript Challenge
Type Challenge #1042. IsNever
Ссылка на задачу
Ссылка на песочницу с тестами
Условие
Реализовать утилиту
Решение
Очень важная задачка, так как она затрагивает тему "распределенных" условных типов (описание в документации). Когда у нас есть дженерик с условным типом (extends) и он получает в качестве параметра union, он себя ведет "распределенно", то есть применяется к каждому элементу объединения.
И тут мы иногда имеем странные вещи:
Штука в том, что распределенный условный тип
Есть лайфхак, чтобы отменить распределенное поведение: обернуть обе части условного типа в квадратные скобки:
Зная это, решение составить очень просто:
#medium
Ссылка на задачу
Ссылка на песочницу с тестами
Условие
Реализовать утилиту
IsNever<T>
, которая возвращает true, если в качестве аргумента получает never. В остальных случаях возвращает false.Решение
Очень важная задачка, так как она затрагивает тему "распределенных" условных типов (описание в документации). Когда у нас есть дженерик с условным типом (extends) и он получает в качестве параметра union, он себя ведет "распределенно", то есть применяется к каждому элементу объединения.
И тут мы иногда имеем странные вещи:
// тут все нормально (без дженериков)
type A = never extends never ? 'yes' : 'no'
let a: A // a: 'yes'
// а тут что-то пошло не так
type B<T> = T extends never ? 'yes' : 'no'
let b: B<never> // b: never
Штука в том, что распределенный условный тип
B
ожидает union, а получает never, который интерпретирует как пустой union - и вообще не выполняется.Есть лайфхак, чтобы отменить распределенное поведение: обернуть обе части условного типа в квадратные скобки:
type B<T> = [T] extends [never] ? 'yes' : 'no'
let b: B<never> // b: 'yes'
Зная это, решение составить очень просто:
type IsNever<T> = [T] extends [never] ? true : false
#medium
GitHub
type-challenges/questions/01042-medium-isnever/README.md at main · type-challenges/type-challenges
Collection of TypeScript type challenges with online judge - type-challenges/type-challenges
👍2