#typescript #typescript-generics
Вопрос:
Я хочу проверить, совпадают ли 2 типа. Я ожидал
export type AreSame<T, U, R> = T extends U ? U extends T ? R : never : never;
работать, но на самом деле это не удается в профсоюзах:
type A = AreSame<1, 1, Object> // Object
type B = AreSame<1, 2, Object> // never
type C = AreSame<1, number, Object> // never
type D = AreSame<1, 1 | 2, Object> // Object - why???
type E = AreSame<1 | 2, 1 | 3, Object> // Object - why???
type F = AreSame<1 | 2, 1 | 2, Object> // Object
Как я могу это исправить?
Ответ №1:
Ваши условные типы случайно являются распределительными. Это означает, что в конечном итоге происходит разделение союзов, оценка типа для каждого члена и объединение их обратно вместе. Пожалуйста, ознакомьтесь с этой документацией, потому что это важно. Если у вас есть тип, например type G<T> = T extends U ? X : Y
, где T
параметр типа «голый» (так что это T extends
и не SomethingWith<T> extends
так), то он будет распространяться. Иногда это то, чего ты хочешь. Сейчас это не так.
Самый простой способ отключить распределительные условные типы-это «одеть» параметр голого типа: превратиться T extends U ? X : Y
в [T] extends [U] ? X : Y
. So:
export type AreSame<T, U, R> = [T] extends [U] ? [U] extends [T] ? R : never : never;
type A = AreSame<1, 1, Object> // Object
type B = AreSame<1, 2, Object> // never
type C = AreSame<1, number, Object> // never
type D = AreSame<1, 1 | 2, Object> // never
type E = AreSame<1 | 2, 1 | 3, Object> // never
type F = AreSame<1 | 2, 1 | 2, Object> // Object
Хорошо, надеюсь, это поможет; удачи!
Ответ №2:
Я просто высказываю предположение, но если мы считаем, что объединение похоже на логическое или, это имело бы смысл.
Позвольте мне попытаться псевдокодировать шаги, необходимые для ответа на этот вопрос..
1 extends (1|2) ? (1|2) extends 1 ? Object : never : never // becomes ->
(1 extends 1 || 1 extends 2) ? (1 extends 1 || 2 extends 1) ? : Object : never : never
Я бы подумал о проверке кода машинописи, чтобы проверить, как именно он работает..
ИЗМЕНИТЬ: Чтобы решить эту проблему, я нашел эту проблему на github в репозитории машинописных текстов
Лучшим решением здесь является следующее:
export type Equals<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
Может быть, вы сможете подогнать это под свой случай? Надеюсь, это поможет 🙂
Комментарии:
1. Это может быть причиной, но что я должен изменить, чтобы это работало так, как мне нужно?