Разница в объявлении дженериков

В машинописном тексте есть ли разница между

a : T<x> | T<y> 

а также

a : T<x | y>

Нет никакой разницы.

Roberto Zvjerković 22.06.2019 17:48

@ritaj посмотри мой ответ

jcalz 22.06.2019 21:35
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
2
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Они нет одинаковы.

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, если они могут быть назначены, зависит от погоды, параметр типа находится в ковариантном контравариантном или бивариантном положении.
Titian Cernicova-Dragomir 22.06.2019 18:39
Ответ принят как подходящий

Это полностью зависит от определения 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 Очень признателен!

MrD 23.06.2019 10:07

Другие вопросы по теме