如何编写一个返回子类型的通用函数

3
根据 Flow文档,Flow中的泛型跟踪值。
这意味着以下代码会引发错误:
function identity<T>(value: T): T {
  if (typeof value === 'string') {
    // $ExpectError
    return '';
  }

  return value;
}

据我所知,他们的文档没有提到如何最好地输入这样的函数。理想情况下,您希望指定该函数返回输入类型的子类型。
具体来说,我想避免那些不太安全的输入类型:
function identity<T>(value: T): (T | string) {
  ...
}

或者

function identity(value: mixed): mixed {
  ...
}

我一直被这个谜团困扰着。非常感谢任何有关此问题的帮助。
谢谢!
1个回答

0

这是一个好问题!我能想到的最好的答案是,你的代码似乎是正确的,流程也应该支持这种情况。同时,你可以在转换回T之前先将其转换为any,以便函数具有正确的签名:

// Has the inferred signature `<T>(value: T) => T`
function identity<T>(value: T) {
  if (typeof value === 'string') {
    return ((value: any): T)
  }

  return value;
}

(试一试)

奇怪的是,我还发现,在值上使用substr并将返回类型注释为T,即使实质上与返回''相同,结果T => T也可以被接受而没有错误(?!?!)

function identity<T>(value: T): T {
  if (typeof value === 'string') {
    return value.substr(0,0)
  }

  return value;
}

(尝试)

也许字面字符串和动态字符串在内部处理上有所不同,导致类型处理上出现了这种奇怪的差异?

从实用的角度来看,如果您最终进行强制转换操作,为这个函数应该处理的不同情况添加单元测试是明智的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接