Javascript 如何表示函数必须以多态方式返回与第一个参数相同的类型?
我一直在阅读有关泛型的文章,希望了解泛型如何在流中工作 我对使用流检查函数编程的函数签名的想法特别感兴趣 但是,我无法理解为什么以下各项不起作用: 当我尝试Javascript 如何表示函数必须以多态方式返回与第一个参数相同的类型?,javascript,generics,flowtype,Javascript,Generics,Flowtype,我一直在阅读有关泛型的文章,希望了解泛型如何在流中工作 我对使用流检查函数编程的函数签名的想法特别感兴趣 但是,我无法理解为什么以下各项不起作用: 当我尝试 /* @flow */ const identity = (c) => c; (identity: <T>(T) => T); // force flow to typecheck 编辑:试图澄清 我主要希望为函数提供一种类型作为参数,并了解如何多态地使用它们 也许这是一个更清楚的例子,说明我正在尝试键入的
/* @flow */
const identity = (c) => c;
(identity: <T>(T) => T); // force flow to typecheck
编辑:试图澄清 我主要希望为函数提供一种类型作为参数,并了解如何多态地使用它们 也许这是一个更清楚的例子,说明我正在尝试键入的内容:
/* @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*/
型式变压器=(T)=>T;
函数transformAGivenThing(转换:Transformer,thing:*){
回归变换(物);
}
函数转换字符串(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`
3:type Transformer=(T)=>T;
^T.此类型与的预期参数类型不兼容
9:函数转换字符串(str:string):字符串{
^串
9:函数转换字符串(str:string):字符串{
^字符串。此类型与的预期参数类型不兼容
13:transformAGivenThing(transformAString,“thing”);
^'T的某些不兼容的实例化`
编辑了关于添加到您的帖子中的内容
/* @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);
/*@flow*/
常量isStr=(str:string)=>!!str;
常量isNmbr=(nmbr:number)=>!!nmbr;
函数transformAny(transformer:(T)=>T,thing:T):T{
回流变压器(物);
}
函数transformString(thing:string):string{
return!!thing?thing.toUpperCase():thing;
}
函数编号(事物编号):编号{
返回!!东西?东西*10:东西;
}
设s=transformAny(transformString,“1”);
设n=transformAny(transformNumber,5);
isStr(s);
//isStr(n);
//isNmbr(s);
isNmbr(n);
取消对typechecking的2个调用的注释将引发错误匹配参数类型。我不认为您可以为其中一个参数声明自定义类型并返回相应的类型。这是我第一次看到这种语言,但它看起来非常类似于TypeScript。编辑了关于添加到您的帖子的内容
/* @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);
/*@flow*/
常量isStr=(str:string)=>!!str;
常量isNmbr=(nmbr:number)=>!!nmbr;
函数transformAny(transformer:(T)=>T,thing:T):T{
回流变压器(物);
}
函数transformString(thing:string):string{
return!!thing?thing.toUpperCase():thing;
}
函数编号(事物编号):编号{
返回!!东西?东西*10:东西;
}
设s=transformAny(transformString,“1”);
设n=transformAny(transformNumber,5);
isStr(s);
//isStr(n);
//isNmbr(s);
isNmbr(n);
取消对typechecking的2个调用的注释将引发错误匹配参数类型。我不认为您可以为其中一个参数声明自定义类型并返回相应的类型。这是我第一次看到这种语言,但它看起来非常类似于TypeScript。好,所以我最后提交了一个问题作为flow他们的回答是:
/* @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'));
/*@flow*/
型式变压器=(T)=>T;
函数transformAGivenThing(转换:Transformer,thing:*){
回归变换(物);
}
函数大写字符串(str:string):string{
return str.toUpperCase();
}
log(transformAGivenThing(大写字母“thing”);
正在发生的事情是,您需要使用类型配置
Transformer
泛型类型,但在这种情况下,因为它需要是多态的,所以配置应该是*
确定的,所以我向flow提交了一个问题,询问如何执行此操作。他们的答案:
/* @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'));
/*@flow*/
型式变压器=(T)=>T;
函数transformAGivenThing(转换:Transformer,thing:*){
回归变换(物);
}
函数大写字符串(str:string):string{
return str.toUpperCase();
}
log(transformAGivenThing(大写字母“thing”);
发生的事情是,你需要用一个类型来配置
Transformer
泛型类型,但在这种情况下,因为它需要是多态的,所以配置应该是*
嗯,也许我对我在这里试图实现的目标不够清楚。我将尝试更新我的问题。@rickard我已经编辑了我的帖子。这就是你试图对通用对象transformer
所做的吗?嗯,也许我对我试图实现的目标还不够清楚。我将尝试更新我的问题。@rickard我已经编辑了我的帖子。调用let s=transformer>时,这就是你试图对通用对象transformer
所做的吗mAGivenThing(大写“thing”);
,返回的类型将是any
。如果您检查我的更新答案,返回类型将与给定变压器的返回类型相对应。适当的智能感知将拾取该类型。*
和any
*
之间存在差异*
意味着延迟下游的类型检查,而any
表示不进行类型检查。因为*
将类型检查推迟到以后,所以在上面的示例中,泛型中的类型将在flow检查uppercaseString
函数的点处解析。调用时,让s=transformAGivenThing(uppercaseString,'thing');
,返回的类型将是any
。如果您检查我的更新答案,返回类型将与给定变压器的返回类型相对应。适当的智能感知将拾取该类型。*
和any
*
之间存在差异*
意味着延迟下游的类型检查,而any
表示不进行类型检查。因为*
延迟类型检查
/* @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'));