繁体   English   中英

Typescript:为什么我们不能为泛型类型分配默认值?

[英]Typescript: Why is it that we cannot assign default value to generic type?

以下面为例。 我不太确定错误消息的含义,但从逻辑上看,签名是完全有效的。 这只是TS不支持吗?

function _createNominalCollection<isOutputOrdered_T extends boolean>(
  input: nominal_T,
  processingFunc: (count: number) => number,
  orderedOutput: isOutputOrdered_T = true,
)

^^^
Type 'boolean' is not assignable to type 'isOutputOrdered_T'.
  'boolean' is assignable to the constraint of type 'isOutputOrdered_T', but 'isOutputOrdered_T' could be instantiated with a different subtype of constraint 'boolean'.ts(2322)

正如@VLAZ 指出的_createNominalCollection<false>()是有问题的。 让我们再看看这个错误:

“布尔”可分配给“isOutputOrdered_T”类型的约束,但“isOutputOrdered_T”可以用约束“布尔”的不同子类型实例化。ts(2322)

这意味着您将显式<false>类型作为通用参数传递, isOutputOrdered_T现在被限制为false但默认参数为true ,这将违反这一点。

或者换句话说, truefalseboolean的子类型,而您的 function 允许 boolean 被约束到这些子类型中的所有子类型,但不会保证所有子类型的分配。

让我提出一个替代方案。


When you have a function that returns different types based on different arguments, you should always consider if function overloads are better suited to model that instead of generics. 它们允许您以简单的方式将 map 参数模式专门用于特定的返回类型,而根本不需要任何 generics。

例如:

// sorted version
function myFn(orderedOutput?: true): 'sorted'

// unsorted version
function myFn(orderedOutput: false): 'unsorted'

// Implementation
function myFn(orderedOutput: boolean = true): 'sorted' | 'unsorted' {
  return orderedOutput ? 'sorted' : 'unsorted'
}

// Testing
const a = myFn(true) // sorted
const b = myFn(false) // unsorted
const c = myFn() // sorted

在这里,您为 function 创建两个签名。 第一个“排序”版本不接受任何参数或true 第二个“未排序”版本接受false 然后你有一个处理这两种情况的实现。

操场

您收到此错误的原因是因为 isOutputOrdered_T 可能是 boolean 子类型,例如type truthy = truetype falsy = false ,而不是完整的 boolean,例如type bool = true | false type bool = true | false的。 例如:

function _createNominalCollection<T extends boolean>(
  orderedOutput: T
) {}

type booleanSubtype = true;

_createNominalCollection<booleanSubtype>(false);

在这个例子中,编译器会抱怨传递 false,因为booleanSubtype只允许 true 作为输入:

“false”类型的参数不能分配给“true”类型的参数

如果是真实的 boolean 子类型,就像在示例中一样,您的默认值将不是有效输入,这就是编译器警告您的原因。 如果您像这样键入默认值,则您的示例可以在没有编译器警告的情况下工作:

function _createNominalCollection<T extends boolean>(
  orderedOutput: T = false as T
) {}

但如前所示,这对于真实的子类型实际上并不正确,只是消除了错误。

您可以选择不将默认值分配给 false - 将其保留为未定义。

function f<T extends boolean=false>(a?: T) {
   return a ? 'isTrue' : 'isNotTrue'
}

我想我会质疑为什么你首先需要这个通用的。 返回类型是否会根据此标志而改变? 如果它确实改变了为什么它需要是单个 function,那么拥有 2 个不同名称的函数不是更有意义吗?

您收到错误是因为您将true分配给orderedOutput作为默认参数。

如果您调用_createNominalCollection(..,..,false)约束类型参数isOutputOrdered_T将被推断为false 当然,不允许将值true分配给false类型的参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM