为什么TS中的泛型接口不能正确推断类型?推断、接口、正确、类型

由网友(隐瞒了意图)分享简介:一旦在泛型接口中使用了Explicit_value扩展Explicit_value,即使代码是100%正确的,TS的类型系统也会变得愚蠢。function fn(param: T): T {if (param === "a") return "a"/* <-- errorT...

一旦在泛型接口中使用了Explicit_value扩展Explicit_value,即使代码是100%正确的,TS的类型系统也会变得愚蠢。

function fn<T extends "a" | "b">(param: T): T {
    if (param === "a") return "a"/* <-- error
Type '"a"' is not assignable to type 'T'.
  '"a"' is assignable to the constraint of type 'T',
  but 'T' could be instantiated with a different subtype of constraint '"a" | "b"'.
 */
    else return "b"/* <-- error
Type '"b"' is not assignable to type 'T'.
  '"b"' is assignable to the constraint of type 'T',
  but 'T' could be instantiated with a different subtype of constraint '"a" | "b"'.
 */
}

//that's ok:
function fn2<T extends string>(param: T): T {
    return param
}

//even this:
function fn3<T extends "a">(): T {
    return "a"/* <-- error
Type '"a"' is not assignable to type 'T'.
  '"a"' is assignable to the constraint of type 'T',
  but 'T' could be instantiated with a different subtype of constraint '"a"'.
 */
}

推荐答案

我不会说它很愚蠢。它只是很安全。 请考虑以下示例:

function fn3<T extends "a">(): T {
  return "a" // error

}

const result = fn3<'a' & { tag: 2 }>().tag // 2
根据下面四种细胞器的模式图.分析下列说法正确的是 A.结构甲具有双层膜.能够对蛋白质进行加工.分类.包装B.结构乙是由单层膜连接成的网状结构.其上面可附着核糖体

表示T扩展了a,但不等于‘a’。 在上面示例中,result2,但在运行时它等于undefined

这就是为什么TS会给您一个错误。泛型参数应与运行时值绑定。就像您在第二个示例中所做的那样。

让我们看看您的第一个示例:

function fn<T extends "a" | "b">(param: T): T {
  if (param === "a") return "a"
  else return "b"

}


错误:

"";a";"可赋给类型为"T"的约束,但"T"可以用约束"";a";|";b";""的不同子类型实例化。

请记住,这并不意味着T总是等于abT可以是此约束/并集的任何子类型。 例如,您可以使用never,它是类型System:

的底层类型
const throwError = () => {
  throw Error('Hello')
}

fn<'a' | 'b'>(throwError())

fn是否有可能返回ab?不,它将引发错误。也许这不是最好的例子,只是想向您展示不同子类型的含义。

让我们用不同的子类型集调用fn

declare var a: 'a' & { tag: 'hello' }

const result = fn(a).tag // undefined

你可能会说:嘿,你没有按规则行事。类型'a' & { tag: 'hello' }在运行时不可表示。事实上,情况并非如此。tag在运行时将始终为undefined。 但是,我们处于类型范围内。我们可以很容易地创建这样的类型。

摘要

请不要将extends视为等号运算符。它只是意味着T可以是已定义约束的任意子类型。

P.S.类型在TypeScrip中是不变的。这意味着,一旦您创建了带有某些约束的类型T,则无法返回具有其他约束的相同泛型参数T。我的意思是,在您的第一个示例中,返回类型T不能仅为a或仅为b。它将始终为a | b

阅读全文

相关推荐

最新文章