【问题标题】:TypeScript can't resolve tuple in function genericsTypeScript 无法解析函数泛型中的元组
【发布时间】:2020-05-08 12:56:19
【问题描述】:

我正在尝试使用具有泛型返回类型的重载函数的联合类型,当元组类型作为泛型传递时,TypeScript 似乎丢失了:

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 的限制/错误?

【问题讨论】:

    标签: typescript generics types tuples


    【解决方案1】:

    这里的问题是 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,它将正确的类型明确定义为返回类型。只有当您想要手动输入常量值时,问题才会出现,因为您在你的例子中做。

    【讨论】:

      猜你喜欢
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      • 2019-01-11
      相关资源
      最近更新 更多