Машинопись> Обобщения> Ограничение Союза - PullRequest
0 голосов
/ 05 мая 2019

Почему компилятор машинописи выдает следующую ошибку:

Operator '+' cannot be applied to types 'T' and 'T'. * * 1004

при компиляции:

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => param1 + param2

1 Ответ

4 голосов
/ 05 мая 2019

Соответствующая проблема в GitHub: Microsoft / TypeScript # 12410 .Ваш конкретный вопрос рассматривается в комментарии Райан Кавано :

T + T, где T расширяется string | number все еще не разрешено - мыне думаю, что это хороший вариант использования, потому что, если вы получаете конкатенацию или сложение, не предсказуемо, то есть то, что людям не следует делать.

То же самое происходит с вами, если вы просто попытаетесьсложить два string | number типа вместе:

declare const x: string | number;
x + x; // error!
// Operator '+' cannot be applied to types 'string | number' and 'string | number'.

Так что я думаю, они серьезно, что они не хотят, чтобы вы это делали.Вы всегда можете согнуть компилятор по своему желанию и отключить проверку типа с помощью подтверждения типа ;

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => (param1 as any) + param2;

Но вы не хотите этого делать, тем более что T extends string | number будет вывод a строка или число литерал, который не дает ожидаемого поведения:

const notThree = addNumbersOrCombineStrings(1, 2);
// const notThree: 1 | 2

const notHi = addNumbersOrCombineStrings("h", "i");
// const notHi: "h" | "i"

Ой, эти результаты являются объединениямилитералов.И чтобы исправить это, используя дженерики, вы, вероятно, захотите начать использовать необычные условные типы для расширения литералов:

type SN<T extends string | number> = (T extends string ? string : never) | 
  (T extends number ? number : never);

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: SN<T>
): SN<T> =>
  (param1 as any) + param2;

const n = addNumbersOrCombineStrings(1, 2); // const n : number;
const s = addNumbersOrCombineStrings("h","i"); // const s: string;

// and do you even want to support this:
const sn = addNumbersOrCombineStrings(
  Math.random() < 0.5 ? "a" : 1,
  Math.random() < 0.5 ? "b" : 2
); // const sn: string | number;

Но, возможно, есть и крайние случаи (например, когдапереданное значение на самом деле string | number, как в случае sn выше).Я начинаю понимать, почему они не хотят добавлять значения типа string | number вместе.Во всяком случае, надеюсь, что это помогает.Удачи!

...