不能满足打字稿类型函数的返回类型

时间:2018-04-30 12:38:33

标签: typescript

说我有这种类型:

  export type Transformer = <T extends any[], U>(
    data: T,
  ) => U;

我有这个功能,我想要符合这种类型:

export const transform: Transformer = (
  data: Result[]
): { data:Result[] } => {
  if (!data) {
    return { data: [] };
  }


  data.forEach((record:Result) => {
    record.extraStuff = {
      foo: 'bar'
    };
  });

  return { data: data };
};

编译器抱怨:

Type '(data: Result[]) => { data: RecordMatchingSearchResult[]; }' is not assignable to type 'Transformer'.
  Type '{ data: Result[]; }' is not assignable to type 'U'.

我是否需要向U添加通用约束以推断它。

我也没有编写类型,但它似乎有点奇怪,它不接受泛型参数,但它们存在于函数中。

1 个答案:

答案 0 :(得分:3)

你的功能问题在于它并不是真正的通用。您有一个通用函数签名(Transformer),并且您尝试分配一个非通用的函数。

返回类型特别是因为返回类型必须由调用者指定,因此调用者将指望它指定的返回类型而不是非泛型结果({ data: Result[] })。如果允许您的分配,则此调用将导致运行时错误:

let result = transform<Result[], { other: number }>([]);
result.other // this would cause an error 

如果结果的类型是固定的,你应该声明它,并且函数实现本身应该是通用的:

export type Transformer = <T extends { extraStuff: any }>(
    data: T[],
) => { data: T[] };

class Result {
    extraStuff: any;
}
export const transform: Transformer = <T extends { extraStuff: any }>(data: T[]): { data: T[] } => {
    if (!data) {
        return { data: [] };
    }


    data.forEach((record: T) => {
        record.extraStuff = {
            foo: 'bar'
        };
    });

    return { data: data };
};

或者您可以将Transfomer的泛型从函数签名移动到类型,并在声明transform函数时指定类型参数,因此函数本身不必是通用的:

export type Transformer<T extends { extraStuff: any }, U> = (
    data: T[],
) => U;

export const transform: Transformer<Result, { data: Result[] }> = (data: Result[]): { data: Result[] } => {
    if (!data) {
        return { data: [] };
    }


    data.forEach((record: T) => {
        record.extraStuff = {
            foo: 'bar'
        };
    });

    return { data: data };
};