Как стать автором
Обновить

Комментарии 11

Очень интересно! По сути игнорирование лишних полей это такая структурная типизация? Хотя и в С++ такое есть, производные классы (с лишними полями) можно использовать вместо базовых...

И еще, понятия "тип-сумма" и "тип-произведение" это ведь не совсем объединение и пересечение типов? Тип-сумма A+B может одновременно вместить объект только одного типа (A или B), а тип-объединение также может включать и пересечение типов (A&B), которое по сути является слиянием полей двух типов в один. Получается что тип-сумма это tagged union, а тип-объединение - tagged struct ?

Нет, тип-объединение - это вообще не tagged что-то там. Это буквально объединение множеств, только с типами.

Тип-произведение тоже никакого отношения к пересечению типов не имеет, тип-произведение это кортеж, ну или тот самый struct.

По сути игнорирование лишних полей это такая структурная типизация?

Удивительно, в языке со структурной типизацией вы нашли структурную типизацию...

Вы кстати отвечали мне на похожий вопрос здесь. Я не пишу на TypeScript, но система типов у него очень интересная, а я пытаюсь сопоставить ее с системами типов других языков, от того и задаю такие вопросы:)

тип-произведение это кортеж, ну или тот самый struct

Кстати, сам по себе кортеж в TS, например, [1|2, 3|4], не будет "полноценным" произведением, например, сужение типов (narrowing) не умеет с ним работать.

Пример. Если заменить для переменной х тип T на MT, то ошибок нет.

Есть даже тайп-челлендж на эту тему, с произвольной рекурсивной дистрибуцией.

Не вполне понятна связь между сужением типов и полноценностью произведения...

Хороший вопрос! Типизация в TS структурная. Сами объединения в TS - untagged, хотя можно уточнить принадлежность к типу. А вообще провести параллели между типом-суммой и типом-произведением с объединением и пересечением в TS - неплохая тема для отдельного поста.

Добавлю ещё от себя.

1) При пересечении объектов, если есть совпадающие ключи, то значения в этих ключах пересекаются: {a: A, b: B1} & {c: C, b: B2} = {a: A, b: B1 & B2, c: C}

2) Пересечение функций - то же самое, что их перегрузка.

3) Объединение функций можно рассматривать как одну функцию, аргументы которой являются пересечениями:

type F = ((a: 1 | 2, b: 5 | 6) => void) | ((a: 2 | 3) => void);

declare const f: F; // возможные вызовы: f(2, 5) и f(2, 6)

Здесь первый параметр стал пересечением, а второй нет, но он обязателен. Суть: мы не знаем, какая именно функция из двух возможных в переменной f, но пересечения подходят для обеих.

При пересечении объектов, если есть совпадающие ключи, то значения в этих ключах пересекаются

Только пересекаются всё-таки типы, а не объекты.

Объединение функций можно рассматривать как одну функцию, аргументы которой являются пересечениями

В контравариантной позиции объединения выводится пересечение, это не только с функциями работает.

type X<in T> = {}

type t1 = X<1 | 2> | X<2 | 3> extends X<infer R> ? R : never // 2

Спасибо, это интересно. Один момент, второй пример как будто не удачный, там же нет ничего неожиданного - тип FnObjArg требует чтобы аргумент содержал число n:

type FnObjArg = { n: number };
const arg2 = {m: 2} as const;
const res = fn(arg);

В оригинальном примере в доках тип объявляет все члены как необязательные, но при передаче аргумента с какими-то другими полями возникает ошибка.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории