Комментарии 16
Очень круто. Спасибо
У Вас случаем нет заполненной таблицы (матрицы) отношений всех указанных типов на одном экране? Возможно курьезов найдется больше )
У Дарта же средства работы с типами совсем бедненькие.
я бы сказал пора решать проблемы людей с помощью программирования, а не создавать новые)
Спасибо за статью!
Строго говоря, в TypeScript есть два отношения на типах: subtyping и assignability. Большая часть таких странностей относится именно к assignability, которое, как раз-таки, проверяется в conditional types. Но это скорее терминологические придирки, потому что в большинстве видимых программисту случаев используется таки assignability.
А в каких видимых случаях не используется assignability?
К примеру, при overload resolution. Выбирается первая подходящая перегрузка, при этом аргументы сравниваются по отношению подтипа.
enum Enum { Value = 123 };
const e: Enum = 456; // number is assignable to any enum
declare function f(x: Enum): true;
declare function f(x: number): false;
const x = f(123); // x: false
const y = f(Enum.Value); // y: true
Я ориентировался на старую спеку, но, похоже, что в этом отношении ничего не изменилось.
Кстати, f(123 as any)
будет иметь тип true
несмотря на то, что any
— не подтип number
или Enum
. Но это объясняется той же спекой:
- когда формируется список сигнатур-кандидатов, между аргументами используется отношение assignability
- когда в этом списке ищется подходящая, используется отношение subtyping
- если подходящих нет (как в нашем случае с
any
), берется первая из списка
Не, тогда получается, что number подтип Enum, ибо при перегрузках выбирается наиболее узкий тип. А вот если декларации поменять местами, то последнее выражение выдаёт false, то есть выбирается первая попавшаяся перегрузка, а значит компилятор считает их равнозначными.
enum Enum { Value = 123 };
const e: Enum = 456; // number is assignable to any enum
const o: 123 = Enum.Value; // enum is assignable only to this number
declare function f(x: number): 2;
declare function f(x: Enum): 1;
// declare function f(x: 123): 3;
const x = f(123); // x: 2
const y = f(Enum.Value); // y: 2
Да, похоже, вы правы. Мне сложно приводить примеры, потому что спека уже очень старая, а с кодом самого компиляторя я мало знаком.
На самом деле, даже официальная документация, несмотря на эту ремарку, часто использует просто слово compatible
, не уточняя, о каком именно отношении идет речь.
ТайпСкрип: Ох уж эта весёлая система типов