如何表示函数必须以多态方式返回与第一个参数相同的类型?

时间:2017-07-20 10:23:31

标签: javascript generics flowtype

我一直在阅读有关泛型的内容,并希望了解泛型如何在流程中工作。

https://flow.org/en/docs/types/generics/#toc-function-types-with-generics

我特别感兴趣的是使用flow来检查功能编程的函数签名。

但是我无法理解为什么以下不起作用:

当我尝试

/* @flow */

const identity = (c) => c;

(identity: <T>(T) => T); // force flow to typecheck

然后Flow返回错误:

3: const identity = (c) => c;
                           ^ T. This type is incompatible with
5: (identity: <T>(T) => T);
    ^ some incompatible instantiation of `T`

我原以为是因为c总是c并且没有变异,所以它的类型必须与模式匹配?

问:我如何表示该函数必须返回与第一个参数相同的类型?

免费示例

即使我尝试使用类型别名,它似乎也不起作用。

/* @flow */
type ReturnsSameTypeAsFirstParam = <T>(T) => T;

const identity:ReturnsSameTypeAsFirstParam = (c) => c;
然后我得到:

4: const identity:ReturnsSameTypeAsFirstParam = (c) => c;
                                                       ^ T. This type is incompatible with
4: const identity:ReturnsSameTypeAsFirstParam = (c) => c;
                                                ^ some incompatible instantiation of `T`

编辑:尝试澄清

我主要希望为函数提供一个类型作为参数,并了解如何以多态方式使用它们。

也许这是我想要输入的那种东西的更清晰的例子:

/* @flow */

type Transformer = <T>(T)=>T;

function transformAGivenThing(transform:Transformer, thing:*) {
  return transform(thing);
}

function transformAString(str:string):string {
  return str.toUpperCase();
}

transformAGivenThing(transformAString, 'thing');

当我运行flow时,这会导致这些错误:

3: type Transformer = <T>(T)=>T;
                       ^ T. This type is incompatible with the expected param type of
9: function transformAString(str:string):string {
                             ^ string
9: function transformAString(str:string):string {
                                         ^ string. This type is incompatible with the expected param type of
13: transformAGivenThing(transformAString, 'thing');
                     ^ some incompatible instantiation of `T`

2 个答案:

答案 0 :(得分:0)

关于添加到您的帖子进行了编辑。

/* @flow */

const isStr = (str: string) => !!str;
const isNmbr = (nmbr: number) => !!nmbr;

function transformAny<T>(transformer: (T) => T, thing: T): T {
  return transformer(thing);
}

function transformString(thing: string): string {
  return !!thing ? thing.toUpperCase() : thing;
}

function transformNumber(thing: number): number {
  return !!thing ? thing * 10 : thing;
}

let s = transformAny(transformString, "1");

let n = transformAny(transformNumber, 5);

isStr(s);
// isStr(n);
// isNmbr(s);
isNmbr(n);

取消注释2次类型检查调用将引发错配匹配参数类型的错误。我不认为您可以为其中一个参数声明自定义类型并返回相应的类型。这是我第一次看到这种语言,但它看起来与TypeScript非常相似。

答案 1 :(得分:0)

好的,所以我最后提交了一个问题,要求提供方法。他们的答案是:

/* @flow */

type Transformer<T> = (T)=>T;

function transformAGivenThing(transform:Transformer<*>, thing:*) {
  return transform(thing);
}

function uppercaseAString(str:string):string {
  return str.toUpperCase();
}

console.log(transformAGivenThing(uppercaseAString, 'thing'));

https://github.com/facebook/flow/issues/4429

发生的事情是您需要使用Type配置Transformer泛型类型,但在这种情况下,因为它需要是多态的,配置应该是*