TypeScript не может разрешить кортеж в обобщениях функций - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь использовать перегруженные функции объединенного типа с возвращаемым типом generi c, и кажется, что TypeScript теряется, когда тип кортежа передается как обобщенный c:

type Fn1<R> = (one: string) => R;
type Fn2<R> = (one: string, two: string) => R;
type Fn3<R> = (one: string, two: string, three: string) => R;
type GenericOverloadingFn<R> = Fn1<R> | Fn2<R> | Fn3<R>;

type TupleOfPrimitives = [
  string,
  number
];

type StructWithKeys = {
  one: string;
  two: number;
}

type UnionFn = GenericOverloadingFn<TupleOfPrimitives>
  | GenericOverloadingFn<string>
  | GenericOverloadingFn<StructWithKeys>; 

type UnionGenericFn = GenericOverloadingFn<
  TupleOfPrimitives
  | string
  | StructWithKeys
>; 

const union2Fn0: UnionFn = (one: string, two: string) => "hey"; // works
const union2Fn1: UnionFn = (one: string, two: string) => ({ one: "hey", two: 1 }); // works
const union2Fn2: UnionFn = (one: string, two: string) => ["hey", 2]; // error

const union1Fn0: UnionFn = (one: string) => ["hey", 2]; // error
const union3Fn0: UnionFn = (one: string, two: string, three: string) => ["hey", 2]; // works


const unionGeneric2Fn0: UnionGenericFn = (one: string, two: string) => "hey"; // works
const unionGeneric2Fn1: UnionGenericFn = (one: string, two: string) => ({ one: "hey", two: 1 }); // works
const unionGeneric2Fn2: UnionGenericFn = (one: string, two: string) => ["hey", 2]; // error

const unionGeneric3Fn2: UnionGenericFn = (one: string, two: string, three: string) => ["hey", 2]; // works


const fn20: Fn2<TupleOfPrimitives> = (one: string, two: string) => ["hey", 2]; // works
const fn21: Fn2<string | TupleOfPrimitives> = (one: string, two: string) => "hey"; // works
const fn22: Fn2<string | TupleOfPrimitives> = (one: string, two: string) => ["hey", 2]; // works


const genericOverloading2Fn: GenericOverloadingFn<TupleOfPrimitives> =
  (one: string, two: string) => ["hey", 2]; // error

const genericOverloading3Fn: GenericOverloadingFn<TupleOfPrimitives> =
  (one: string, two: string, three: string) => ["hey", 2]; // works

Ошибки в основном выглядят так

Type '(one: string, two: string) => (string | number)[]' is not assignable to type 'UnionFn'.
  Type '(one: string, two: string) => (string | number)[]' is not assignable to type 'Fn1<TupleOfPrimitives>'.

Я не уверен, что делаю что-то не так или это ограничение / ошибка в TypeScript?

1 Ответ

1 голос
/ 22 января 2020

Проблема здесь в выводе TypeScript, который шире, чем требуется вашему типу. Мы можем просто проверить, какой тип имеет такую ​​конструкцию:

const a = ['a', 1];
type A = typeof a; // (string | number)[]

Итак, ясно, что (string | number)[] является более широким типом, чем [string, number], и возникает проблема. Чтобы исправить это просто, нам нужно применить утверждение типа:

 (one: string) => ['a', 1] as TupleOfPrimitives

Также учтите, что в поле, скорее всего, вы не будете возвращать только const, но будут некоторые другие вызовы функций, и в этой ситуации вероятно, вы избежите утверждения. Рассмотрим пример:

const g = (one: string): TupleOfPrimitives => [one, 1]; 
const f: GenericOverloadingFn<TupleOfPrimitives> = (one: string) => g(one)

Функция f не нуждается в утверждении внутри, поскольку она вызывает функцию g, которая четко определяет правильный тип в качестве возвращаемого типа. Проблема возникнет только тогда, когда вы захотите ставить постоянное значение вручную, как вы делаете в своих примерах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...