В машинописном тексте есть ли разница между
a : T<x> | T<y>
а также
a : T<x | y>
@ritaj посмотри мой ответ
Они нет одинаковы.
a: T<x> | T<y>
означает, что a
имеет либо типа T<x>
или T<y>
.
a: T<x | y>
означает, что a
имеет тип T
, где T
является общим над типом x | y
.
Любое значение типа T<x> | T<y>
можно присвоить любой переменной типа T<x | y>
, но не наоборот.
Я сделал быстрая демонстрация, демонстрирующий это.
Any value of type T<x> | T<y> is assignable to any variable of type T<x | y>, but not the other way around.
False, если они могут быть назначены, зависит от погоды, параметр типа находится в ковариантном контравариантном или бивариантном положении.
Это полностью зависит от определения T
, которое здесь не включено. Поскольку код не похож на минимальный воспроизводимый пример, мы можем говорить только в общих чертах.
Когда вы говорите, что T<X | Y>
эквивалентно T<X> | T<Y>
для всех X
и Y
, вы говорите, что T<X>
распределяет над объединениями в параметре типа. В общем, T<X>
распределяет нет по своему параметру типа. Это могу происходит, но обычно этого не происходит.
Чтобы изучить некоторые случаи, давайте представим некоторое тестовое оборудование:
type Compare<U, V> = [U] extends [V]
? ([V] extends [U] ? "mutually assignable" : "subtype")
: [V] extends [U] ? "supertype" : "unrelated";
Тип Compare<U, V>
сравнивает типы U
и V
, чтобы определить, можно ли U
присвоить V
и/или наоборот. Если T<X | Y>
совпадает с T<X> | T<Y>
, то Compare<T<X | Y>, T<X> | T<Y>>
должно вернуть "mutually assignable"
. Если нет, то вы получите одну из трех других возможностей: либо T<X | Y>
является супертип для T<X> | T<Y>
(то есть T<X> | T<Y>
присваивается T<X | Y>
), либо T<X | Y>
является подтип для T<X> | T<Y>
(то есть T<X | Y>
присваивается T<X> | T<Y>
), или T<X | Y>
является несвязанный для T<X> | T<Y>
(то есть ни один тип не может быть присвоен другому).
type X = { a: string; b: number } | number;
type Y = { c: boolean; d: any[] } | string;
У меня есть пример особый для X
и Y
здесь, поэтому в следующих тестах, если T<X | Y>
объявляется эквивалентным T<X> | T<Y>
, для общих X
и Y
верно только свидетельство, а не доказательство. Очевидно, что если я выберу X
и Y
одного типа, то T<X | Y>
всегда будет равно T<X> | T<Y>
. Поэтому я только что выбрал достаточно разные X
и Y
для наглядности.
Хорошо, приступим:
Вот некоторые универсальные типы, которые являются распределяются по объединениям в их параметре типа, где T<X> | T<Y>
эквивалентно T<X | Y>
:
• Функции постоянного типа, которые не обращаются к своему параметру типа, являются дистрибутивными:
type Constant<T> = string;
type ConstantDistributes = Compare<Constant<X | Y>, Constant<X> | Constant<Y>>;
// mutually assignable
• Функция типа идентичности является распределительной:
type Identity<T> = T;
type IdentityDistributes = Compare<Identity<X | Y>, Identity<X> | Identity<Y>>;
// mutually assignable
• Объединение параметра типа с чем-либо является дистрибутивным:
type OrSomething<T> = T | { z: string };
type OrSomethingDistributes = Compare<
OrSomething<X | Y>,
OrSomething<X> | OrSomething<Y>
>; // mutually assignable
• Пересечение параметра типа с чем-либо является дистрибутивным:
type AndSomething<T> = T & { z: string };
type AndSomethingDistributes = Compare<
AndSomething<X | Y>,
AndSomething<X> | AndSomething<Y>
>; // mutually assignable
• условный тип, в котором проверяемый тип является "голым" параметром типа (то есть просто T extends ...
вместо SomeFunctionOf<T> extends ...
) является дистрибутивным:
type NakedConditional<T> = T extends object ? { x: T } : { y: T };
type NakedConditionalDistributes = Compare<
NakedConditional<X | Y>,
NakedConditional<X> | NakedConditional<Y>
>; // mutually assignable
• Универсальный тип, который имеет значение бивариантный в параметре типа, является дистрибутивным. Это довольно редко, так как бивариантные типы, как правило, несостоятельны. Параметры метода в TypeScript — трактуется как бивариантный. Параметры функции в целом рассматриваются как бивариантные, если вы отключите --strictFunctionTypes
... но вы не должны отключать это.
interface Bivariant<T> {
method(x: T): void;
}
type BivariantDistributes = Compare<
Bivariant<X | Y>,
Bivariant<X> | Bivariant<Y>
>;
// mutually assignable
Эти случаи были выбраны специально для обеспечения эквивалентности. Теперь о более распространенных случаях, когда они эквивалентны нет:
• Универсальный тип, параметр type которого равен ковариантный, будет распространять нет. В таких типах T<X | Y>
будет супертип от T<X> | T<Y>
:
interface Covariant<T> {
prop: T;
}
type CovariantIsASupertype = Compare<
Covariant<X | Y>,
Covariant<X> | Covariant<Y>
>;
// supertype
• Универсальный тип, параметр type которого равен контравариантный, будет распространять нет. В таких типах T<X | Y>
будет подтип от T<X> | T<Y>
:
interface Contravariant<T> {
(arg: T): void;
}
type ContravariantIsASubtype = Compare<
Contravariant<X | Y>,
Contravariant<X> | Contravariant<Y>
>;
// subtype
• Универсальный тип, параметр type которого равен инвариант, будет распространять нет. В таких типах T<X | Y>
будет не связанный с от T<X> | T<Y>
:
interface Invariant<T> {
(arg: T): T;
}
type InvariantIsUnrelated = Compare<
Invariant<X | Y>,
Invariant<X> | Invariant<Y>
>;
// unrelated
Давайте резюмируем. Ничего не зная о T
, вы не можете рассчитывать на то, что T<X | Y>
будет эквивалентно T<X> | T<Y>
для всех X
и Y
. Есть несколько конкретных случаев T
, когда известно, что он распределяется по союзам, и в этих случаях нет никакой разницы. Хотя обычно разница есть.
Хорошо, надеюсь, это поможет. Удачи!
Ну, мне нужно будет выделить время, чтобы пройтись по всему этому, но это просто мое незнание предмета. Это один из самых подробных ответов, которые я получил на ТАК, большое спасибо!! :D Очень признателен!
Нет никакой разницы.